通过切面类对方法添加分布式redis锁demo

本文介绍了如何使用Java的Spring AOP和自定义注解@RedisLock,为方法提供分布式锁功能。通过RedisLock注解配置活动键、锁值、有效期等,并展示了切面类RedisLockAspect的实现,包括前置通知加锁和后置通知解锁。实例演示了如何在@RequestMapping方法上应用该注解进行并发控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、创建注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface RedisLock {
    /** 活动key */
    String activityKey() default "";

    /** 锁存储字符串 */
    String valueStr() default "1";

    /** 有效期,默认1 */
    long timeout() default 1;

    /** 有效期单位,默认秒 */
    TimeUnit timeUnit() default TimeUnit.SECONDS;

    /** 是否在方法执行完成后删除 */
    boolean overDel() default true;
}

2、创建切面类

/**
 * 使用redis锁注解对方法加锁
 * @author lei.yan004
 */
@Component
@Aspect
public class RedisLockAspect {

    private static final Logger logger = LoggerFactory.getLogger(RedisLockAspect.class);

    @Autowired
    private RedisUtil redisUtil;

    // 声明公共切入点
    @Pointcut("@annotation(com.sinolife.lock.RedisLock)")
    private void lockPointCut() {
    }

    /**
     * 方法执行前调用,用于请求加锁
     * @param joinPoint
     * @return
     */
    @Around(value = "lockPointCut()")
    public Object lockAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RedisLock annotation = method.getAnnotation(RedisLock.class);

        String userId = PlatformContext.currentUser();
        if (StringUtil.isDataEmpty(userId)) {
            return ResponseResult.fail("登陆超时,请重新登陆");
        }
        String redisKey = RedisKeyConstant.REDIS_KEY_PUB_LIMIT ;
        if(StringUtils.isNotBlank(annotation.activityKey())){
            redisKey += annotation.activityKey() + ":" ;
        }
        redisKey += method.getName() + ":" + userId;
        boolean setResult = redisUtil.setIfAbsent(redisKey, annotation.valueStr(), annotation.timeout(), annotation.timeUnit());
        if (!setResult) {
            return ResponseResult.fail("正在处理中,请勿重复操作");
        }
        return joinPoint.proceed();
    }

    /**
     * 方法执行完成后调用,用于释放锁
     * @param joinPoint
     * @return
     * @Author lei.yan004
     */
    @After("lockPointCut()")
    public void lockAfter(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RedisLock annotation = method.getAnnotation(RedisLock.class);
        if (annotation.overDel()) {
            String userId = PlatformContext.currentUser();
            String redisKey = RedisKeyConstant.REDIS_KEY_PUB_LIMIT;
            if (StringUtils.isNotBlank(annotation.activityKey())) {
                redisKey += annotation.activityKey() + ":";
            }
            redisKey += method.getName() + ":" + userId;
            redisUtil.delete(redisKey);
        }
    }
}

3、使用demo

可以通过RedisLock注解的属性,进行一些自定义的配置,例如有效期等

@RedisLock
@RequestMapping("/updateScene")
public ResponseResult<Map<String,Object>> updateScene() {
	...
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值