自定义redis锁注解类定义
redis锁注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRedisLockAnnotation {
/**
* 锁的key值前缀
* @return
*/
String keyPrefix() default "";
/**
* 锁后缀:方法入参表达式springEl
* @return
*/
String keyExpression() default "";
/**
* 锁最大等待时间
* @return
*/
long waitTime() default 30000;
/**
* 锁最大持有时间,默认30秒,根据需求实际修改,-1:开启看门狗防止锁提前释放
* @return
*/
long leaseTime() default 30000;
}
Spring AOP配置
@Slf4j
@Aspect
@Component
public class MyLockAspect {
@Resource
RedissonDistributedLocker redissonDistributedLocker;
@Around("@annotation(myRedisLockAnnotation)")
public Object around(ProceedingJoinPoint joinPoint, MyRedisLockAnnotation myRedisLockAnnotation) throws Throwable{
String lockKey = myRedisLockAnnotation.keyPrefix();
try {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
lockKey = lockKey + parseKeySpEl(joinPoint,myRedisLockAnnotation.keyExpression());
AssertUtil.isTrue(StringUtil.isNotEmpty(lockKey),method.getDeclaringClass().getSimpleName()+"."+method.getName()+"MyRedisLockAnnotation配置异常,redis锁的key不能为空!");
boolean isLock = redissonDistributedLocker.tryLock(lockKey, TimeUnit.MILLISECONDS, myRedisLockAnnotation.waitTime(), myRedisLockAnnotation.leaseTime());
if (!isLock) {
throw new BusinessException(method.getDeclaringClass().getSimpleName()+"."+method.getName()+"锁获取失败,请稍后重试~");
}
return joinPoint.proceed();
}finally {
redissonDistributedLocker.unlock(lockKey);
}
}
private String parseKeySpEl(ProceedingJoinPoint joinPoint,String keySpEl) {
if(StringUtils.isBlank(keySpEl)){
return "";
}
// 通过joinPoint获取被注解方法
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
//创建解析器
SpelExpressionParser parser = new SpelExpressionParser();
//获取表达式
Expression expression = parser.parseExpression(keySpEl);
//设置解析上下文(有哪些占位符,以及每种占位符的值)
EvaluationContext context = new StandardEvaluationContext();
//获取参数值
Object[] args = joinPoint.getArgs();
//获取运行时参数的名称
DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
String[] parameterNames = discoverer.getParameterNames(method);
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i],args[i]);
}
//解析,获取替换后的结果
String result = expression.getValue(context, String.class);
return null == result?"":result;
}
}
RedissonDistributedLocker 替换成自己项目封装的redis锁工具类就好
使用
@Override
@MyRedisLockAnnotation(keyPrefix = "ihd_test_Lock_" ,keyExpression = "#saveDTO.orgCode",waitTime = 20000,leaseTime = -1)
public WebResponse<XXXVO> saveXXX(XXXSaveDTO saveDTO) {
...
}
总结
一切都是为了偷懒,不用每个要加锁的方法都要写一套trylock