edc71ec8a79ae5e3ac993517363ed903124542fe.svn-base 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package org.jeecg.boot.starter.lock.aspect;
  2. import lombok.SneakyThrows;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.aspectj.lang.ProceedingJoinPoint;
  5. import org.aspectj.lang.annotation.Around;
  6. import org.aspectj.lang.annotation.Aspect;
  7. import org.aspectj.lang.reflect.MethodSignature;
  8. import org.jeecg.boot.starter.lock.annotation.JLock;
  9. import org.jeecg.boot.starter.lock.enums.LockModel;
  10. import org.redisson.RedissonMultiLock;
  11. import org.redisson.RedissonRedLock;
  12. import org.redisson.api.RLock;
  13. import org.redisson.api.RedissonClient;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
  16. import org.springframework.expression.EvaluationContext;
  17. import org.springframework.expression.Expression;
  18. import org.springframework.expression.ExpressionParser;
  19. import org.springframework.expression.spel.standard.SpelExpressionParser;
  20. import org.springframework.expression.spel.support.StandardEvaluationContext;
  21. import org.springframework.stereotype.Component;
  22. import java.util.ArrayList;
  23. import java.util.List;
  24. import java.util.concurrent.TimeUnit;
  25. /**
  26. * 分布式锁解析器
  27. *
  28. * @author zyf
  29. * @date 2020-11-11
  30. */
  31. @Slf4j
  32. @Aspect
  33. @Component
  34. public class DistributedLockHandler extends BaseAspect{
  35. @Autowired(required = false)
  36. private RedissonClient redissonClient;
  37. /**
  38. * 切面环绕通知
  39. *
  40. * @param joinPoint
  41. * @param jLock
  42. * @return Object
  43. */
  44. @SneakyThrows
  45. @Around("@annotation(jLock)")
  46. public Object around(ProceedingJoinPoint joinPoint, JLock jLock) {
  47. Object obj = null;
  48. log.info("进入RedisLock环绕通知...");
  49. RLock rLock = getLock(joinPoint, jLock);
  50. boolean res = false;
  51. //获取超时时间
  52. long expireSeconds = jLock.expireSeconds();
  53. //等待多久,n秒内获取不到锁,则直接返回
  54. long waitTime = jLock.waitTime();
  55. //执行aop
  56. if (rLock != null) {
  57. try {
  58. if (waitTime == -1) {
  59. res = true;
  60. //一直等待加锁
  61. rLock.lock(expireSeconds, TimeUnit.MILLISECONDS);
  62. } else {
  63. res = rLock.tryLock(waitTime, expireSeconds, TimeUnit.MILLISECONDS);
  64. }
  65. if (res) {
  66. obj = joinPoint.proceed();
  67. } else {
  68. log.error("获取锁异常");
  69. }
  70. } finally {
  71. if (res) {
  72. rLock.unlock();
  73. }
  74. }
  75. }
  76. log.info("结束RedisLock环绕通知...");
  77. return obj;
  78. }
  79. @SneakyThrows
  80. private RLock getLock(ProceedingJoinPoint joinPoint, JLock jLock) {
  81. String[] keys = jLock.lockKey();
  82. if (keys.length == 0) {
  83. throw new RuntimeException("keys不能为空");
  84. }
  85. String[] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(((MethodSignature) joinPoint.getSignature()).getMethod());
  86. Object[] args = joinPoint.getArgs();
  87. LockModel lockModel = jLock.lockModel();
  88. if (!lockModel.equals(LockModel.MULTIPLE) && !lockModel.equals(LockModel.REDLOCK) && keys.length > 1) {
  89. throw new RuntimeException("参数有多个,锁模式为->" + lockModel.name() + ".无法锁定");
  90. }
  91. RLock rLock = null;
  92. String keyConstant = jLock.keyConstant();
  93. if (lockModel.equals(LockModel.AUTO)) {
  94. if (keys.length > 1) {
  95. lockModel = LockModel.REDLOCK;
  96. } else {
  97. lockModel = LockModel.REENTRANT;
  98. }
  99. }
  100. switch (lockModel) {
  101. case FAIR:
  102. rLock = redissonClient.getFairLock(getValueBySpEL(keys[0], parameterNames, args, keyConstant).get(0));
  103. break;
  104. case REDLOCK:
  105. List<RLock> rLocks = new ArrayList<>();
  106. for (String key : keys) {
  107. List<String> valueBySpEL = getValueBySpEL(key, parameterNames, args, keyConstant);
  108. for (String s : valueBySpEL) {
  109. rLocks.add(redissonClient.getLock(s));
  110. }
  111. }
  112. RLock[] locks = new RLock[rLocks.size()];
  113. int index = 0;
  114. for (RLock r : rLocks) {
  115. locks[index++] = r;
  116. }
  117. rLock = new RedissonRedLock(locks);
  118. break;
  119. case MULTIPLE:
  120. rLocks = new ArrayList<>();
  121. for (String key : keys) {
  122. List<String> valueBySpEL = getValueBySpEL(key, parameterNames, args, keyConstant);
  123. for (String s : valueBySpEL) {
  124. rLocks.add(redissonClient.getLock(s));
  125. }
  126. }
  127. locks = new RLock[rLocks.size()];
  128. index = 0;
  129. for (RLock r : rLocks) {
  130. locks[index++] = r;
  131. }
  132. rLock = new RedissonMultiLock(locks);
  133. break;
  134. case REENTRANT:
  135. List<String> valueBySpEL = getValueBySpEL(keys[0], parameterNames, args, keyConstant);
  136. //如果spel表达式是数组或者LIST 则使用红锁
  137. if (valueBySpEL.size() == 1) {
  138. rLock = redissonClient.getLock(valueBySpEL.get(0));
  139. } else {
  140. locks = new RLock[valueBySpEL.size()];
  141. index = 0;
  142. for (String s : valueBySpEL) {
  143. locks[index++] = redissonClient.getLock(s);
  144. }
  145. rLock = new RedissonRedLock(locks);
  146. }
  147. break;
  148. case READ:
  149. rLock = redissonClient.getReadWriteLock(getValueBySpEL(keys[0], parameterNames, args, keyConstant).get(0)).readLock();
  150. break;
  151. case WRITE:
  152. rLock = redissonClient.getReadWriteLock(getValueBySpEL(keys[0], parameterNames, args, keyConstant).get(0)).writeLock();
  153. break;
  154. }
  155. return rLock;
  156. }
  157. }