springboot整合redis+自定义注解+反射+aop实现分布式锁

news2024/11/28 11:47:41

1.定义注解

import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;

/** @Author: best_liu
 * @Description:
 * @Date: 16:13 2023/9/4
 * @Param 
 * @return 
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface RedisLock {
    String lockPrefix() default "";

    String lockKey() default "";

    //是否使用自定义过期时间,false->配置文件获取;true->自己指定过期时间
    boolean expireConfig() default true;

    long timeOut() default 30;

    TimeUnit timeUnit() default TimeUnit.SECONDS;
}

2.aop+redis

利用redis 的setIfAbsent()方法获取锁

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/** @Author: best_liu
 * @Description:
 * @Date: 16:13 2023/9/4
 * @Param 
 * @return 
 **/
@Aspect
@Component
@Slf4j
public class RedisLockAspect {
    private static final Integer Max_RETRY_COUNT = 3;
    private static final String LOCK_PRE_FIX = "lockPreFix";
    private static final String LOCK_KEY = "lockKey";
    private static final String TIME_OUT = "timeOut";
    private static final String EXPIRE_CONFIG = "expireConfig";

    @Value("${schedule.expire}")
    private long timeOut;

    @Autowired
    private RedisTemplate redisTemplate;

    @Pointcut("@annotation(com.mes.dispatch.annotation.redisLock.RedisLock)")
    public void redisLockAspect() {
    }

    @Around("redisLockAspect()")
    public void lockAroundAction(ProceedingJoinPoint proceeding) throws Exception {

        //获取注解中的参数
        Map<String, Object> annotationArgs = this.getAnnotationArgs(proceeding);
        String lockPrefix = (String) annotationArgs.get(LOCK_PRE_FIX);
        String key = (String) annotationArgs.get(LOCK_KEY);
        long expire = (long) annotationArgs.get(TIME_OUT);
        boolean expireConfig = (boolean) annotationArgs.get(EXPIRE_CONFIG);
        //分布式锁
        boolean lock = false;
        try {
            //如果返回true,说明key不存在,获取到锁
            lock = redisTemplate.opsForValue().setIfAbsent(key, lockPrefix);
            log.info("是否获取到锁:" + lock);
            if (lock) {
                log.info("获取到锁,开启定时任务!");
                //设置过期时间
                if (expireConfig) {
                    redisTemplate.expire(key, expire, TimeUnit.SECONDS);
                } else {
                    redisTemplate.expire(key, timeOut, TimeUnit.SECONDS);
                }

                proceeding.proceed();
            } else {
                log.info("其他系统正在执行此项任务");
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throw new RuntimeException("分布式锁执行发生异常" + throwable.getMessage(), throwable);
        }
    }

    /**
     * 获取锁参数
     *
     * @param proceeding
     * @return
     */
    private Map<String, Object> getAnnotationArgs(ProceedingJoinPoint proceeding) {
        Class target = proceeding.getTarget().getClass();
        Method[] methods = target.getMethods();
        String methodName = proceeding.getSignature().getName();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Map<String, Object> result = new HashMap<String, Object>();
                RedisLock redisLock = method.getAnnotation(RedisLock.class);
                result.put(LOCK_PRE_FIX, redisLock.lockPrefix());
                result.put(LOCK_KEY, redisLock.lockKey());
                result.put(TIME_OUT, redisLock.timeUnit().toSeconds(redisLock.timeOut()));
                result.put(EXPIRE_CONFIG, redisLock.expireConfig());
                return result;
            }
        }
        return null;
    }

}

3.使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1266709.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么把dwg格式转换pdf?

怎么把dwg格式转换pdf&#xff1f;DWG是一种由AutoCAD开发的二维和三维计算机辅助设计&#xff08;CAD&#xff09;文件格式&#xff0c;它的名称是“绘图&#xff08;Drawing&#xff09;”的缩写。DWG文件通常包含了设计图纸、模型和元数据等信息&#xff0c;并且被广泛用于工…

工艺系统所管理数字化实践

摘要 本文介绍了上海核工程设计研究院在数字化转型方面的实践&#xff0c;包括业务数字化和管理数字化两个方面。业务数字化方面&#xff0c;该院通过开发小工具改进工作流程。管理数字化方面&#xff0c;该院采用零代码平台集中管理管道力学信息相关模型和数据&#xff0c;并…

Martin Fowler:数字化时代,远程与本地协同工作孰优孰劣?(2)| IDCF

作者&#xff1a;Martin Fowler 译者&#xff1a;冬哥 原文&#xff1a;https://martinfowler.com/articles/remote-or-co-located.html &#xff08;接上篇 &#xff09; 二、大多数人在同地办公时工作效率更高 与软件开发中的许多主题一样&#xff0c;我不能拿 100 个软…

Sectigo通配符证书

Sectigo通配符证书&#xff08;Wildcard SSL Certificate&#xff09;是一种特殊类型的SSL证书&#xff0c;它适用于一个主域名及其所有子域名。这意味着&#xff0c;只要子域名在主域名下&#xff0c;就可以使用同一张通配符证书进行加密保护。这为拥有多个子域名的网站提供了…

探究Kafka原理-7.exactly once semantics 和 性能测试

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理&#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44…

方差分析汇总

一文整理了方差分析的全部内容&#xff0c;包括方差分析的定义&#xff08;基本思想、检验统计量的计算、前提条件&#xff09;、方差分析分类&#xff08;单因素、双因素、多因素、事后多重比较、协方差分析、重复测量方差分析&#xff09;、方差分析流程&#xff08;数据格式…

四川天蝶电子商务有限公司真实可靠吗?

随着数字经济的不断发展&#xff0c;抖音电商服务日益成为企业拓展销售渠道、提升品牌影响力的关键一环。在这样的大背景下&#xff0c;四川天蝶电子商务有限公司凭借其专业的服务能力和创新的技术手段&#xff0c;迅速崛起为抖音电商服务领域的领军企业。 四川天蝶电子商务有限…

使用 ZFPlayer 播放视频的注意点

一 静音功能 通过调用系统的AVPlayer.muted来实现的 - (void)setMuted:(BOOL)muted {_muted muted;self.player.muted muted;if (self.audioMuteChange) {self.audioMuteChange(self, muted);}... }播放进度条 /// 滑杆 property (nonatomic, strong, readonly) ZFSliderV…

04、基于高斯分布的异常检测算法

04、基于高斯分布的异常检测算法原理与实践 开始学习机器学习啦&#xff0c;已经把吴恩达的课全部刷完了&#xff0c;现在开始熟悉一下复现代码。对这个手写数字实部比较感兴趣&#xff0c;作为入门的素材非常合适。 数据的严重偏斜往往会导致监督学习算法面临巨大的挑战——…

亚马逊云科技 re:Invent 2023:引领科技前沿,探索未来云计算之窗

文章目录 一、前言二、什么是亚马逊云科技 re:Invent&#xff1f;三、亚马逊云科技 re:Invent 2023 将于何时何地举行四、亚马逊云科技 re:Invent 2023 有什么内容&#xff1f;4.1 亚马逊云科技 re:Invent 2023 主题演讲4.2 亚马逊云科技行业专家探实战 五、更多亚马逊云科技活…

发牌洗牌的简单逻辑

1. 需求分析 1.1 要求实现&#xff1a; 我们能使用一副牌&#xff0c;基本的实现多人炸金花小游戏。 1.2 实现分析&#xff1a; 1、有一副牌&#xff1a; 首先自定义card类&#xff0c;来定义每一张牌&#xff1b;&#xff08;牌上由花色和数字&#xff08;1~13&#xff09;&…

第二十章多线程

线程简介 java语言提供了并发机制&#xff0c;程序员可以在程序中执行多个线程&#xff0c;每一个线程完成一个功能&#xff0c;并与其他线程并发运行。 一个进程是一个包含有自身地址的程序&#xff0c;每个独立执行的程序都称为进程。也就是说每个正在执行的程序都是一个进…

基于QT的俄罗斯方块游戏设计与实现

基于QT的俄罗斯方块游戏设计与实现 摘要&#xff1a;信息时代正处于高速发展中&#xff0c;而电子游戏已经成为人生活中或不可少的消磨工具之一。科技时代在不断地高速发展中&#xff0c;游戏相关编程设计也随着发展变得越来越重要&#xff0c; 俄罗斯方块游戏是一款古老传遍世…

ubuntu22.04新机使用(换源,下载软件,安装显卡驱动,锁屏长亮)

换源 国内有很多Ubuntu的镜像源&#xff0c;包括阿里的、网易的&#xff0c;还有很多教育网的源&#xff0c;比如&#xff1a;清华源、中科大源。推荐使用中科大源&#xff0c;快得很。 /etc/apt/sources.list编辑/etc/apt/sources.list文件, 在文件最前面添加以下条目(操作前…

促进高层次人才创新创业,长沙又在“放大招”

“人才”&#xff0c;寥寥数笔&#xff0c;却勾勒出一座城市的发展核心、创新引擎。大力引进高层次人才&#xff0c;更是城市提升综合实力的有效举措。 11月26日&#xff0c;在长沙市委组织部&#xff08;市委人才工作局&#xff09;举办“汇聚磅礴力量 全力建设全球研发中心城…

港科夜闻|2023年全球大学毕业生就业力排名公布,香港科大位列香港第一名

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、2023年全球大学毕业生就业力排名公布&#xff0c;香港科大位列香港第一名。香港科大在泰晤士高等教育2023年全球就业能力大学排名中上升一位至全球第29位&#xff0c;继续位居香港首位。香港科大的毕业生就业能力持续跻身…

水淼采集器-免费水淼采集器下载

在当今数字时代&#xff0c;随着信息的迅猛增长&#xff0c;许多网站管理员面临一个共同而具有挑战性的问题——如何在短时间内获取大量优质内容&#xff0c;以满足用户对信息的不断需求&#xff1f;水淼采集器&#xff0c;作为一个备受瞩目的解决方案&#xff0c;正成为许多人…

浅谈数据资产价值评估

加gzh"大数据食铁兽“&#xff0c;了解更多大数据信息 数据是资产&#xff0c;是当前时代大背景下毋庸置疑的。随着科技的发展&#xff0c;数据的重要性越来越受到人们的关注。对于企业来说&#xff0c;数据是非常重要的资产&#xff0c;它可以为企业提供决策依据、增加市…

Leetcode—2336.无限集中的最小数字【中等】

2023每日刷题&#xff08;四十四&#xff09; Leetcode—2336.无限集中的最小数字 实现代码 class SmallestInfiniteSet {set<int> s; public:SmallestInfiniteSet() {for(int i 1; i < 1000; i) {s.insert(i);}}int popSmallest() {int res *s.begin();s.erase(s…