使用Aspect+自定义注解实现redis锁,防止重复触发

使用Aspect+自定义注解实现redis锁,防止重复触发

自定义注解类

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisLock {
    String value() default "default_lock:";
}

切面类

@Aspect
//@Order(1)
@Component
public class RedisLockAspect {
//    @Around("@annotation(com.common.aspect.RedisLock)")
    @Around("@annotation(redisLock)")
    public Object lock(ProceedingJoinPoint point, RedisLock redisLock) {
        //获取参数
        Object[] args = point.getArgs();
        Object result = null;
        int length = args.length;
        if (args != null && length > 0) {
            try {
                //默认锁第一个参数,userid
                String userid = String.valueOf(args[0]);
                //锁的key
                String lockName = redisLock.value()+userid;
                Boolean aBoolean = RedisHelper.setNX(lockName, "1");
                if (!aBoolean) {
                    result = Utils.toJSON("请求过于频繁,请稍后再试", null, "1");;
                } else {
                    //设置缓存时间,这个地方报错可能会产生死锁 设置缓存时间 60s(秒)
                    RedisHelper.expire(lockName, 60);
                    //执行方法
                    result = point.proceed(args);
                    //方法执行完,删除key
                    RedisHelper.del(lockName);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
        return result;
    } 
}

RedisHelper是操作redis的工具类,网上有很多,不上传了。
切面类中
1.@Around();环绕通知, 包围一个join point(连接点)的通知,如方法调用。这是最强大的一种通知 类型。 环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。
2.point.proceed(args); 执行目标方法(标注注解的方法)。
3. RedisHelper.setNX(lockName, “1”); 这是redis的工具类,就不发了,setNX命令就是 set not exist,
如果redis缓存中存在该key值,不更新,返回false,不存在就存入redis缓存中。返回true。
RedisHelper.expire(lockName, 60); 设置缓存时间 60s
4.例子中的redis锁的key是@RedisLock 中的参数和方法的第一个参数组成的。

切入点表达式:
@annotation(com.common.aspect.RedisLock) 任何一个执行的方法有一个 @RedisLock 注解的连接点(在Spring AOP中只是方法执行)(标注@RedisLock注解的方法)
@annotation(redisLock) 如果在@RedisLock 注解中使用参数名字代替参数类型,那么当通知执行的时候,对应的参数值会被传入。(@RedisLock注解本身可以作为切面方法中的参数,方便获取注解中的参数值)

使用实例:

@Service
public class TestService {
   	 @RedisLock(“test”)
    public Object test1(String userid) {
        return1111111111;
    }
}

就这样只要我们业务中有需要加锁的业务方法上面只需要加上@RedisLock注解就可以,防止重复触发方法了。

可以使用jmeter进行压力测试。

注意:标注@RedisLock注解的方法需要至少有一个参数,一般在service中的非静态方法上使用

github上翻译的spring framework 中文文档,有点老了,可以看看:https://github.com/waylau/spring-framework-4-reference

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值