提交 3d6cd0dd 编写于 作者: zlt2000's avatar zlt2000

分布式锁增加注解调用方式

上级 f32bd3c4
package com.central.common.lock;
import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;
/**
* @author zlt
* @date 2020/6/6
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lock {
/**
* 锁的key
*/
String key();
/**
* 获取锁的最大尝试时间(单位毫秒)
* 该值大于0则使用 locker.tryLock 方法加锁,否则使用 locker.lock 方法
*/
long waitTime() default 0;
/**
* 加锁的时间,超过这个时间后锁便自动解锁;
* 如果leaseTime为-1,则保持锁定直到显式解锁
*/
long leaseTime() default -1;
/**
* 参数的时间单位
*/
TimeUnit unit() default TimeUnit.SECONDS;
/**
* 是否公平锁
*/
boolean isFair() default false;
}
package com.central.common.lock;
import cn.hutool.core.util.StrUtil;
import com.central.common.exception.LockException;
import lombok.extern.slf4j.Slf4j;
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.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
/**
* 分布式锁切面
*
* @author zlt
* @date 2020/6/6
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Slf4j
@Aspect
public class LockAspect {
private DistributedLock locker;
public LockAspect(DistributedLock locker) {
this.locker = locker;
}
/**
* 用于SpEL表达式解析.
*/
private SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
/**
* 用于获取方法参数定义名字.
*/
private DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
@Around("@within(lock) || @annotation(lock)")
public Object aroundLock(ProceedingJoinPoint point, Lock lock) throws Throwable {
Object lockObj = null;
if (lock == null) {
// 获取类上的注解
lock = point.getTarget().getClass().getDeclaredAnnotation(Lock.class);
}
String lockKey = lock.key();
if (locker == null) {
throw new LockException("DistributedLock is null");
}
if (StrUtil.isEmpty(lockKey)) {
throw new LockException("lockKey is null");
}
if (lockKey.contains("#")) {
MethodSignature methodSignature = (MethodSignature)point.getSignature();
//获取方法参数值
Object[] args = point.getArgs();
lockKey = getValBySpEL(lockKey, methodSignature, args);
}
try {
//加锁
if (lock.waitTime() > 0) {
lockObj = locker.tryLock(lockKey, lock.waitTime(), lock.leaseTime(), lock.unit(), lock.isFair());
} else {
lockObj = locker.lock(lockKey, lock.leaseTime(), lock.unit(), lock.isFair());
}
if (lockObj != null) {
return point.proceed();
} else {
throw new LockException("锁等待超时");
}
} finally {
locker.unlock(lockObj);
}
}
/**
* 解析spEL表达式
*/
private String getValBySpEL(String spEL, MethodSignature methodSignature, Object[] args) {
//获取方法形参名数组
String[] paramNames = nameDiscoverer.getParameterNames(methodSignature.getMethod());
if (paramNames != null && paramNames.length > 0) {
Expression expression = spelExpressionParser.parseExpression(spEL);
// spring的表达式上下文对象
EvaluationContext context = new StandardEvaluationContext();
// 给上下文赋值
for(int i = 0; i < args.length; i++) {
context.setVariable(paramNames[i], args[i]);
}
return expression.getValue(context).toString();
}
return null;
}
}
......@@ -2,4 +2,5 @@ org.springframework.context.ApplicationContextInitializer=\
com.central.common.config.BannerInitializer
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.central.common.feign.fallback.UserServiceFallbackFactory
\ No newline at end of file
com.central.common.feign.fallback.UserServiceFallbackFactory,\
com.central.common.lock.LockAspect
\ No newline at end of file
......@@ -7,6 +7,7 @@ import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import java.util.concurrent.TimeUnit;
......@@ -21,6 +22,7 @@ import java.util.concurrent.TimeUnit;
* Github: https://github.com/zlt2000
*/
@ConditionalOnClass(RedissonClient.class)
@ConditionalOnProperty(prefix = "zlt.lock", name = "lockerType", havingValue = "REDIS", matchIfMissing = true)
public class RedissonDistributedLock implements DistributedLock {
@Autowired
private RedissonClient redisson;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册