基于SpringBoot AOP面向切面编程实现Redis分布式锁

基于SpringBoot AOP面向切面编程实现Redis分布式锁

基于SpringBoot AOP面向切面编程实现Redis分布式锁

锁定的目标是确保相互排斥其访问的资源。实际上,此资源通常是字符串。使用redis实现锁主要是将资源放入redis中并利用其原子性。当其他线程访问时,如果Redis中已经存在此资源,则不允许进行某些后续操作。

Spring Boot通过RedisTemplate使用Redis,在实际使用过程中,分布式锁可以在封装后在方法级别使用,这样使用起来就更方便了,无需到处获取和释放锁。

首先,定义一个注解:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface RedisLock { //锁定的资源,redis的键
    String value() default "default"; //锁定保持时间(以毫秒为单位)
    long keepMills() default 30000; //失败时执行的操作
    LockFailAction action() default LockFailAction.CONTINUE; //失败时执行的操作--枚举
    public enum LockFailAction{
        GIVEUP,
        CONTINUE;
    }
//重试的间隔
    long sleepMills() default 200;
//重试次数
    int retryTimes() default 5;
}

具有分布式锁的Bean

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class DistributedLockAutoConfiguration {   
@Bean   
@ConditionalOnBean(RedisTemplate.class)   
public DistributedLock redisDistributedLock(RedisTemplate redisTemplate){       
  return new RedisDistributedLock(redisTemplate);   
}
}

面向切面编程-定义切面

@Aspect
@Configuration
@ConditionalOnClass(DistributedLock.class)
@AutoConfigureAfter(DistributedLockAutoConfiguration.class)
public class DistributedLockAspectConfiguration {     private final Logger logger = LoggerFactory.getLogger(DistributedLockAspectConfiguration.class);     @Autowired
    private DistributedLock distributedLock;     @Pointcut("@annotation(com.itopener.lock.redis.spring.boot.autoconfigure.annotations.RedisLock)")
    private void lockPoint(){     }     @Around("lockPoint()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
        RedisLock redisLock = method.getAnnotation(RedisLock.class);
        String key = redisLock.value();
        if(StringUtils.isEmpty(key)){
            Object\[\] args = pjp.getArgs();
            key = Arrays.toString(args);
        }
        int retryTimes = redisLock.action().equals(LockFailAction.CONTINUE) ? redisLock.retryTimes() : 0;
//获取分布式锁
        boolean lock = distributedLock.lock(key, redisLock.keepMills(), retryTimes, redisLock.sleepMills());
        if(!lock) {
            logger.debug("get lock failed : " + key);
            return null;
        } //执行方法之后,释放分布式锁
        logger.debug("get lock success : " + key);
        try {
            return pjp.proceed(); //执行方法
        } catch (Exception e) {
            logger.error("execute locked method occured an exception", e);
        } finally {
            boolean releaseResult = distributedLock.releaseLock(key); //释放分布式锁
            logger.debug("release lock :" + key + (releaseResult ?" success" : "failed"));
        }
        return null;
    }
}

使用方法

  • 进入该方法时,占用分布式锁,
  • 方法执行完成时,释放分布式锁
  • 使用同一个资源,如your-custom-service-redis-key的多个函数,抢占同一个锁。谁抢到谁先执行。
@RedisLock(value="your-custom-service-redis-key")
public void serviceMethod(){
//正常写方法实现
}

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

最新文章

  1. C# cmd执行命令
  2. Android驱动开发之Hello实例
  3. this.down和this.up用法
  4. 设计模式(15)-Facade Pattern
  5. 智能车学习(十)——MMA8451加速度计的使用
  6. mysql学习(七)-索引学习
  7. Tomcat与web程序结构与Http协议
  8. maven生成war包的两种方式
  9. [TCP/IP] 数据链路层-ethereal 抓包分析数据帧
  10. 微信小程序 地图地址解析
  11. 来自于一个问题的回答对自己的反思 php怎么发送邮件?发送邮件插件PHPMailer
  12. C程序设计实践教学提示
  13. cf-Global Round2-C. Ramesses and Corner Inversion(思维)
  14. NumPy 从已有的数组创建数组
  15. Miller_raibin算法随机化检测素数 & Pollar_rho 算法分解大数
  16. git cherry-pick 用法
  17. Vue父子组件之间通信
  18. Orchard模块开发全接触4:深度改造前台
  19. javaScript中用eval()方法转换json对象
  20. Maven 在eclipse中如何配置

热门文章

  1. 几种常见的dfs模板
  2. [原创][开源] SunnyUI.Net 字体图标
  3. 【JUC系列】01、之大话并发
  4. count(1) AND count(*) 对比
  5. JavaScript触发器
  6. 单页面应用下刷新当前iframe
  7. mysql字符串类型(TEXT 类型)
  8. pip超时问题解决
  9. yii2.0AR两表联查
  10. cb36a_c++_STL_算法_区间的比较equal_mismatch_lexicographical_compare