自定义redis锁注解实现

自定义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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值