1. 程式人生 > >基於SpringBoot AOP面向切面程式設計實現Redis分散式鎖

基於SpringBoot AOP面向切面程式設計實現Redis分散式鎖

![](https://img2020.cnblogs.com/other/1815316/202007/1815316-20200708094430273-1467040799.png) **基於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(){ //正常寫方法實現 } ~~~ ## 歡迎關注我的部落格,裡面有很多精品合集 * 本文轉載註明出處(必須帶連線,不能只轉文字):[字母哥部落格](http://www.zimug.com)。 **覺得對您有幫助的話,幫我點贊、分享!您的支援是我不竭的創作動力!** 。另外,筆者最近一段時間輸出瞭如下的精品內容,期待您的關注。 * [《手摸手教你學Spring Boot2.0》]( https://www.kancloud.cn/hanxt/springboot2/content ) * [《Spring Security-JWT-OAuth2一本通》](https://www.kancloud.cn/hanxt/springsecurity/content) * [《實戰前後端分離RBAC許可權管理系統》](https://www.kancloud.cn/hanxt/vue-spring/content) * [《實戰SpringCloud微服務從青銅到王者》](https://www.kancloud.cn/hanxt/vue-spring/content) * [《VUE深入淺出系列》](https://www.kancloud.cn/hanxt/vuejs2/