RedisLockAspect.java 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package com.izouma.nineth.aspect;
  2. import com.izouma.nineth.annotations.RedisLock;
  3. import com.izouma.nineth.exception.BusinessException;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.aspectj.lang.ProceedingJoinPoint;
  6. import org.aspectj.lang.annotation.Around;
  7. import org.aspectj.lang.annotation.Aspect;
  8. import org.aspectj.lang.annotation.Pointcut;
  9. import org.aspectj.lang.reflect.MethodSignature;
  10. import org.redisson.api.RLock;
  11. import org.redisson.api.RedissonClient;
  12. import org.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.core.DefaultParameterNameDiscoverer;
  14. import org.springframework.data.redis.core.BoundValueOperations;
  15. import org.springframework.data.redis.core.RedisTemplate;
  16. import org.springframework.expression.EvaluationContext;
  17. import org.springframework.expression.ExpressionParser;
  18. import org.springframework.expression.spel.standard.SpelExpressionParser;
  19. import org.springframework.expression.spel.support.StandardEvaluationContext;
  20. import org.springframework.stereotype.Component;
  21. import java.lang.reflect.Method;
  22. import java.util.Optional;
  23. @Aspect
  24. @Component
  25. @Slf4j
  26. public class RedisLockAspect {
  27. private final DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
  28. private final RedissonClient redissonClient;
  29. public RedisLockAspect(RedissonClient redissonClient) {
  30. this.redissonClient = redissonClient;
  31. }
  32. @Pointcut("@annotation(com.izouma.nineth.annotations.RedisLock)")
  33. public void redisLockPointCut() {
  34. }
  35. @Around(value = "redisLockPointCut() && @annotation(redisLock)")
  36. public Object redisLock(ProceedingJoinPoint joinPoint, RedisLock redisLock) {
  37. ExpressionParser parser = new SpelExpressionParser();
  38. EvaluationContext context = new StandardEvaluationContext(joinPoint.getSignature());
  39. MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
  40. Method method = methodSignature.getMethod();
  41. String[] paramNames = nameDiscoverer.getParameterNames(method);
  42. Object[] args = joinPoint.getArgs();
  43. for (int i = 0; i < args.length; i++) {
  44. context.setVariable(paramNames[i], args[i]);
  45. }
  46. String key = redisLock.value();
  47. try {
  48. key = Optional.ofNullable(parser.parseExpression(redisLock.value()).getValue(context))
  49. .map(Object::toString)
  50. .orElse("default");
  51. } catch (Exception ignored) {
  52. }
  53. log.info("enter redisLock aspect key: {}", key);
  54. RLock lock = redissonClient.getLock(key);
  55. if (redisLock.behavior() == RedisLock.Behavior.WAIT) {
  56. lock.lock(redisLock.expire(), redisLock.unit());
  57. log.info("get redisLock success");
  58. } else {
  59. if (!lock.tryLock()) {
  60. log.info("get redisLock fail");
  61. throw new BusinessException(redisLock.message());
  62. }
  63. log.info("get redisLock success");
  64. }
  65. Object res = null;
  66. try {
  67. res = joinPoint.proceed();
  68. try {
  69. lock.unlock();
  70. } catch (Exception ignored) {
  71. }
  72. } catch (Throwable e) {
  73. try {
  74. lock.unlock();
  75. } catch (Exception ignored) {
  76. }
  77. if (e instanceof BusinessException) {
  78. throw (BusinessException) e;
  79. }
  80. throw new RuntimeException(e);
  81. }
  82. return res;
  83. }
  84. }