|
|
@@ -0,0 +1,113 @@
|
|
|
+package com.fs.framework.aspectj.lock;
|
|
|
+
|
|
|
+import org.aspectj.lang.ProceedingJoinPoint;
|
|
|
+import org.aspectj.lang.annotation.Around;
|
|
|
+import org.aspectj.lang.annotation.Aspect;
|
|
|
+import org.aspectj.lang.reflect.MethodSignature;
|
|
|
+import org.redisson.api.RLock;
|
|
|
+import org.redisson.api.RedissonClient;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.core.StandardReflectionParameterNameDiscoverer;
|
|
|
+import org.springframework.core.annotation.Order;
|
|
|
+import org.springframework.expression.EvaluationContext;
|
|
|
+import org.springframework.expression.Expression;
|
|
|
+import org.springframework.expression.spel.standard.SpelExpressionParser;
|
|
|
+import org.springframework.expression.spel.support.StandardEvaluationContext;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import java.lang.reflect.Method;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+@Aspect
|
|
|
+@Component
|
|
|
+@Order(Integer.MIN_VALUE + 1)
|
|
|
+public class DistributeLockAspect {
|
|
|
+
|
|
|
+ private RedissonClient redissonClient;
|
|
|
+
|
|
|
+ public DistributeLockAspect(RedissonClient redissonClient) {
|
|
|
+ this.redissonClient = redissonClient;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final Logger LOG = LoggerFactory.getLogger(DistributeLockAspect.class);
|
|
|
+
|
|
|
+ @Around("@annotation(com.fs.framework.aspectj.lock.DistributeLock)")
|
|
|
+ public Object process(ProceedingJoinPoint pjp) throws Throwable {
|
|
|
+ Object response = null;
|
|
|
+ Method method = ((MethodSignature) pjp.getSignature()).getMethod();
|
|
|
+ DistributeLock distributeLock = method.getAnnotation(DistributeLock.class);
|
|
|
+
|
|
|
+ String key = distributeLock.key();
|
|
|
+ if (DistributeLockConstant.NONE_KEY.equals(key)) {
|
|
|
+ if (DistributeLockConstant.NONE_KEY.equals(distributeLock.keyExpression())) {
|
|
|
+ throw new DistributeLockException("no lock key found...");
|
|
|
+ }
|
|
|
+ SpelExpressionParser parser = new SpelExpressionParser();
|
|
|
+ Expression expression = parser.parseExpression(distributeLock.keyExpression());
|
|
|
+
|
|
|
+ EvaluationContext context = new StandardEvaluationContext();
|
|
|
+ // 获取参数值
|
|
|
+ Object[] args = pjp.getArgs();
|
|
|
+
|
|
|
+ // 获取运行时参数的名称
|
|
|
+ StandardReflectionParameterNameDiscoverer discoverer
|
|
|
+ = new StandardReflectionParameterNameDiscoverer();
|
|
|
+ String[] parameterNames = discoverer.getParameterNames(method);
|
|
|
+
|
|
|
+ // 将参数绑定到context中
|
|
|
+ if (parameterNames != null) {
|
|
|
+ for (int i = 0; i < parameterNames.length; i++) {
|
|
|
+ context.setVariable(parameterNames[i], args[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析表达式,获取结果
|
|
|
+ key = String.valueOf(expression.getValue(context));
|
|
|
+ }
|
|
|
+
|
|
|
+ String scene = distributeLock.scene();
|
|
|
+
|
|
|
+ String lockKey = scene + "#" + key;
|
|
|
+
|
|
|
+ int expireTime = distributeLock.expireTime();
|
|
|
+ int waitTime = distributeLock.waitTime();
|
|
|
+ RLock rLock= redissonClient.getLock(lockKey);
|
|
|
+ try {
|
|
|
+ boolean lockResult = false;
|
|
|
+ if (waitTime == DistributeLockConstant.DEFAULT_WAIT_TIME) {
|
|
|
+ if (expireTime == DistributeLockConstant.DEFAULT_EXPIRE_TIME) {
|
|
|
+ LOG.info(String.format("lock for key : %s", lockKey));
|
|
|
+ rLock.lock();
|
|
|
+ } else {
|
|
|
+ LOG.info(String.format("lock for key : %s , expire : %s", lockKey, expireTime));
|
|
|
+ rLock.lock(expireTime, TimeUnit.MILLISECONDS);
|
|
|
+ }
|
|
|
+ lockResult = true;
|
|
|
+ } else {
|
|
|
+ if (expireTime == DistributeLockConstant.DEFAULT_EXPIRE_TIME) {
|
|
|
+ LOG.info(String.format("try lock for key : %s , wait : %s", lockKey, waitTime));
|
|
|
+ lockResult = rLock.tryLock(waitTime, TimeUnit.MILLISECONDS);
|
|
|
+ } else {
|
|
|
+ LOG.info(String.format("try lock for key : %s , expire : %s , wait : %s", lockKey, expireTime, waitTime));
|
|
|
+ lockResult = rLock.tryLock(waitTime, expireTime, TimeUnit.MILLISECONDS);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!lockResult) {
|
|
|
+ LOG.warn(String.format("lock failed for key : %s , expire : %s", lockKey, expireTime));
|
|
|
+ throw new DistributeLockException(distributeLock.errorMsg());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ LOG.info(String.format("lock success for key : %s , expire : %s", lockKey, expireTime));
|
|
|
+ response = pjp.proceed();
|
|
|
+ } finally {
|
|
|
+ if (rLock.isHeldByCurrentThread()) {
|
|
|
+ rLock.unlock();
|
|
|
+ LOG.info(String.format("unlock for key : %s , expire : %s", lockKey, expireTime));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+}
|