【Spring】AOP——使用@around实现面向切面的方法增强

工作业务中,有大量分布式加锁的重复代码,存在两个问题,一是代码重复率高,二是容易产生霰弹式修改,使用注解和AOP可以实现代码复用,简化分布式锁加锁和解锁流程。 @around注解是AspectJ框架提供的,允许我们在目标方法的执行前后进行代码增强。下面通过一个示例来介绍如何使用@around注解以及自定义注解实现加解锁(ReenTrantLock)简化。

  1. 改造前原代码 很经典的桥段,初始化10个线程,每个线程分别执行m++1000次,若想得到10000的结果,则必须加锁同步,加锁则需要在执行m++前进行加锁,在finally语句块中执行解锁操作,因此可以通过@around注解实现简化。
    @Service
    @Slf4j
    public class HelloService {private int m = 0;private static int nums = 0;public ReentrantLock lock;// spel表达式private static final String LOCK_KEY = "'asset_tenant_lock_prefix:' +" + "T(org.example.Common.ContextHelper).getTenantInfo().getOrgId()";@AutowiredHelloService helloService;public String doSomeSum() throws InterruptedException {nums++;log.info("调用次数:{}", nums);m = 0;CountDownLatch countDownLatch = new CountDownLatch(10);lock = new ReentrantLock();for (int i = 0; i < 10; i++) {Thread thread = new Thread(() -> {for (int j = 0; j < 1000; j++) {helloService.increM();}countDownLatch.countDown();});thread.start();}countDownLatch.await();return String.valueOf(m);}@DistributeLock(key = LOCK_KEY)public void increM() {lock.lock();try {m++;} finally {lock.unlock();}}
    }
    

 

2. 改造第一步,创建一个注解 注解名为DistributeLock,有一个熟悉key,(这个例子是为了模仿使用Redis分布式锁)

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DistributeLock {String key();
}

3.改造第二步,定义一个切面类 切面类中,定义一个增强方法useDistributeLock,参数joinPoint是切入点,distributeLock是切入点形参,用于传入key。这里我们key使用的是Spel表达式,使用SpelExpressionParser可以求得最终的key值,joinPoint.proceed()执行的则是上文提到的原方法的执行内容,m++。

@Component
@Slf4j
public class DistributeLockAspect {private static ReentrantLock lock = new ReentrantLock();@Around("@annotation(distributeLock)")public Object useDistributeLock(ProceedingJoinPoint joinPoint, DistributeLock distributeLock) throws Throwable {lock.lock();org.springframework.expression.ExpressionParser parser= new SpelExpressionParser();String lockKey = (String) parser.parseExpression(distributeLock.key()).getValue();log.info(lockKey);try {return joinPoint.proceed();} finally {lock.unlock();}}
}

4.改造第三步,使用 使用很简单,只需要在需要增强的方法上加上我们创建的注解,并且给注解的属性Key一个字符串形式的Spel表达式即可实现加解锁操作。代码行数大大减少。

public class HelloService {private int m = 0;private static int nums = 0;public ReentrantLock lock;// spel表达式private static final String LOCK_KEY = "'asset_tenant_lock_prefix:' +" + "T(org.example.Common.ContextHelper).getTenantInfo().getOrgId()";@AutowiredHelloService helloService;public String doSomeSum() throws InterruptedException {nums++;log.info("调用次数:{}", nums);m = 0;CountDownLatch countDownLatch = new CountDownLatch(10);lock = new ReentrantLock();for (int i = 0; i < 10; i++) {Thread thread = new Thread(() -> {for (int j = 0; j < 1000; j++) {helloService.increM();}countDownLatch.countDown();});thread.start();}countDownLatch.await();return String.valueOf(m);}@DistributeLock(key = LOCK_KEY)public void increM() {m++;}
}

5.最终测试结果 最终的测试结果是10000,说明加锁成功

来看看我们日志打印的Lock_key值是否符合预期,符合预期

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode 13. 罗马数字转整数

代码&#xff1a; class Solution(object):def romanToInt(self, s):""":type s: str:rtype: int"""dict1 {I:1,V:5,X:10,L:50,C:100,D:500,M:1000}nums 0t len(s)i 0while i<t :if s[i]I:if i1 t:numsdict1.get(s[i])i1else:if s[i1] V…

关于C#操作SQLite数据库的一些函数封装

主要功能&#xff1a;增删改查、自定义SQL执行、批量执行&#xff08;事务&#xff09;、防SQL注入、异常处理 1.NuGet中安装System.Data.SQLite 2.SQLiteHelper的封装&#xff1a; using System; using System.Collections.Generic; using System.Data.SQLite; using System.…

【云计算】云数据中心网络(一):VPC

云数据中心网络&#xff08;一&#xff09;&#xff1a;VPC 1.什么是 VPC2.VPC 的组成2.1 虚拟交换机2.2 虚拟路由器 3.VPC 网络规划3.1 VPC 数量规划3.2 交换机数量规划3.3 地址空间规划3.4 不同规模企业地址空间规划实践 4.VPC 网络高可靠设计4.1 单地域单可用区部署4.2 单地…

如何配置vite的proxy

1.前言 vite项目&#xff0c;本地开发环境可以通过配置proxy代理实现跨域请求。但是生产环境&#xff0c;该配置不生效&#xff0c;一般使用 nginx 转发&#xff0c;或者后端配置cors 2.解释 server: {port: 9000,proxy: { // 本地开发环境通过代理实现跨域&#xff0c;生产…

【ARM 嵌入式 C 常用数据结构系列 25.1 -- linux 双向链表 list_head 使用详细介绍】

请阅读【嵌入式开发学习必备专栏 】 文章目录 内核双向链表双向链表的数据结构初始化双向链表在双向链表中添加元素遍历双向链表链表使用示例注意事项 内核双向链表 在Linux内核中&#xff0c;双向链表是一种广泛使用的数据结构&#xff0c;允许从任意节点高效地进行前向或后向…

大型语言模型(LLMs)面试常见问题解析

概述 这篇文章[1]是关于大型语言模型&#xff08;LLMs&#xff09;的面试问题和答案&#xff0c;旨在帮助读者准备相关职位的面试。 token&#xff1f; 在大型语言模型中&#xff0c;token 指的是什么&#xff1f; 分词&#xff08;Tokenization&#xff09;&#xff1a;可以将…

ebpf+perfetto实现调度延迟记录与展示

1.背景 需要分析生产环境的调度问题,如线程的调度延迟有多少,在哪些时间点延迟比较明显,影响其调度的主要原因是什么?其次,我们希望可以比较直观的展示调度延迟情况。最好能对接perfetto的UI和后处理,因为perfetto已经用于分析比较多的性能数据,可以和调度数据进行整合.我们…

论文阅读——MVDiffusion

MVDiffusion: Enabling Holistic Multi-view Image Generation with Correspondence-Aware Diffusion 文生图模型 用于根据给定像素到像素对应关系的文本提示生成一致的多视图图像。 MVDiffusion 会在给定任意每个视图文本的情况下合成高分辨率真实感全景图像&#xff0c;或将…

LABVIEW--正弦+高斯噪声信号及滤波

前面板信号 后面板 LABVIEW源程序链接&#xff1a;https://pan.baidu.com/s/11B-75i4fHZwWQyjxn9yCyQ?pwd7tfj 提取码&#xff1a;7tfj

STM32 M3内核寄存器概念

内容主要来自<<M3内核权威指南>> 汇编程序中的最低有效位&#xff08;Least Significant Bit&#xff09;。LSB是二进制数中最右边的位&#xff0c;它代表了数值中的最小单位。在汇编程序中&#xff0c;LSB通常用于表示数据的最小精度或者作为标志位。 ---------…

Linux-exec函数族和system函数

参考资料&#xff1a;《Linux环境编程&#xff1a;从应用到内核》 execve函数 execve函数接口如下&#xff1a; #include <unistd.h>int execve(const char *filename, char *const argv[],char *const envp[]);参数&#xff1a; 第一个参数&#xff1a;filename是可执…

【unity】【C#】延时调用(协程)和场景管理

文章目录 什么是协程协程的应用 - IEnumerator如何控制协程的暂停协程的另一种写法 - Invoke场景管理 多看代码块中的注释 什么是协程 A coroutine alows vou to spreacwhere it left off on the following anc return control toolinencoeframe. 协程允许您将任务分布在多个帧…

数据结构和算法:分治

分治算法 分治&#xff08;divide and conquer&#xff09;&#xff0c;全称分而治之&#xff0c;是一种非常重要且常见的算法策略。分治通常基于递归实现&#xff0c;包括“分”和“治”两个步骤。 1.分&#xff08;划分阶段&#xff09;&#xff1a;递归地将原问题分解为两个…

爬虫部署平台crawlab使用说明

Crawlab 是一个基于 Go 语言的分布式网络爬虫管理平台&#xff0c;它支持 Python、Node.js、Jar、EXE 等多种类型的爬虫。 Crawlab 提供了一个可视化的界面&#xff0c;并且可以通过简单的配置来管理和监控爬虫程序。 以下是 Crawlab 的一些主要优点&#xff1a; 集中管理&am…

数据库不用mmap

你确定你想用 MMAP 实现数据库么&#xff1f;_哔哩哔哩_bilibili MMAP 的随机读与顺序读的性能表现不好&#xff0c;以及对于写主要是不可控的刷入时机以及代码冗余&#xff0c;所以 MMAP 不适合在数据库中使用。 mmap是posix系统调用&#xff0c;它提供由操作系统管理内存映…

自定义实现shell/bash

文章目录 函数和进程之间的相似性shell打印提示符&#xff0c;以及获取用户输入分割用户的输入判断是否是内建命令执行相关的命令 全部代码 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c; 通俗易懂&#xff0c;风趣幽默&#…

GIT版本管理使用示例

一、创建好远程代码仓库后&#xff0c;复制远程仓库的地址 二、新建一个文件夹&#xff0c;在文件夹里打开Git Bash Here 三、输入git clone 远程仓库地址&#xff0c;仓库就初始化完成了 四、新建一个文本文件&#xff0c;假设这是我们开发的代码 五、打开文本&#xff0c;假设…

【深度学习】海洋生物数据集,图片分类

文章目录 任务描述数据收集数据处理模型训练指标评测web app代码和帮助 任务描述 收集9种以上的海洋生物图片&#xff0c;然后基于深度学习做一个分类模型&#xff0c;训练完成后&#xff0c;分类模型就可以对未知图片进行分类。 在之后随便传一张图片&#xff0c;分类模型就…

《乡土中国》中国基层传统社会里的一种体系,支配着社会生活的各方面 - 三余书屋 3ysw.net

乡土中国 大家好&#xff0c;今天我们要解读的是费孝通先生的经典著作《乡土中国》。这本书的中文版大约有10万字&#xff0c;我将用30分钟左右的时间为你解读书中的精髓。为什么说中国的根基在于乡土社会&#xff1f;我们应该从哪些方面来理解乡土社会的特征及其重要性&#…

解压缩软件哪个好用 Mac免费解压软件哪个好 解压软件推荐 beeterzip免费下载

解压缩软件在Mac办公中是必不可少的&#xff0c;不仅能够节省时间和内存&#xff0c;更能提升传输效率。虽然Mac自带的解压缩软件归档实用工具可以对zip文件进行解压&#xff0c;但是对于他格式文件就无能为力了。 因此&#xff0c;想要满足多类型文件解压缩需求&#xff0c;可…