Spring AOP (一)

本篇主要介绍Spring AOP的基础概念和入门使用

一、AOP的基本概念

AOP是一种面向切面编程的思想,它与IOC并称为Spring 的两大核心思想。什么是面向切面编程呢,具体来说就是对一类事情进行集中统一处理。这听起来像不像前面篇章中所介绍的统一功能处理?事实上,统一功能处理确实是对AOP的一种实现,但AOP在Spring中的实现并不仅仅体现于此,因为统一功能处理都是只能针对某种特定的场景,例如拦截器只能在接收请求时进行集中处理,而在Spring 对AOP的实现中,可以自定义要对哪类事情集中处理。

接下来我们来介绍一下AOP的一些相关概念

  • 切面:整个集中处理的过程就叫切面
  • 切点:提供一组规则,来判断要对哪些方法进行集中处理
  • 连接点:满足切点规则的某一个方法,也就是要集中处理的所有方法中的具体的一个方法
  • 通知:集中处理的具体方法逻辑

在Spring中,通知有多种类型:

  • 环绕通知:包含了在连接点执行前与执行后所要执行的逻辑(在Spring中通过@Around注解标注)
  • 前置通知:在连接点执行前所要执行的逻辑(在Spring中通过@Before注解标注)
  • 后置通知:在连接点执行完后所要执行的逻辑(在Spring中通过@After注解标注)
  • 返回后通知:在连接点返回数据后执行,如果连接点在返回数据前发生异常则不会执行(在Spring中通过@AfterReturning注解标注)
  • 异常后通知:在连接点执行过程中发生异常后执行(在Spring中通过@AfterThrowing注解标注)

二、AOP的使用

单一切面

前面我们说过Spring AOP中可以自定义要对哪些类集中处理,因此,接下来我们通过对所有方法集中处理来具体体会一下Spring AOP的使用,集中处理的具体内容为记录所有方法的 执行时间。

首先我们得引入Spring aop的相关依赖:
 

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

然后我们得创建一个切面,具体为创建一个类,在类上加上一个@Aspect注解,用来标注当前类是一个切面类:

然后我们编写切面里包含的切点,通知等内容,由于我们要统计方法执行时间,因此我们可以使用环绕通知来统计也可以使用前置通知和后置通知搭配来统计,这里我们两种都写一下。具体代码如下(目标方法为我们的连接点):

这个切面代码还不能直接使用,因为我们还没有定义切点,我们可以直接将切点定义到通知注解里,具体如下:

关于这里对切点的具体的定义格式我们在下面在进行介绍,这里只要知道这个切点的规则是controller包下的所有方法就行 ,还有我们每次使用通知都得加上这样一个切点。

加好切点以后,一个切面类就定义好了,下面我们定义一个方法来测试一下:

借助浏览器访问这个接口后,控制台的打印如下:

可以发现通知和目标方法是按下图的顺序执行的

 下面我们来了解一下异常后通知:

首先我们先在切面里定义一个异常通知:

然后在controller里新增一个test02方法,在这个方法里定义一个算术异常

然后我们通过浏览器测试一下这个接口,

控制台的输出如下:


 通过日志可以发现,当目标方法发生异常时,环绕通知,和返回后通知都没有在执行了,返回后通知没有执行很好理解,因为目标方法还没有返回数据前发生异常了,所以目标方法就不会有返回值,也就不能触发返回后通知。为什么环绕通知也不执行了呢,我们来看一下执行目标方法的proceed方法的实现:

可以发现它把异常上抛给环绕通知了,所以环绕通知直接结束了。如果我们不想让环绕通知因异常而结束,可以在目标方法里直接将异常catch住,这样异常就不会上抛给环绕通知了,环绕通知也就不会发生影响了,代码如下

我们也可以在环绕通知里对异常进行catch:

 打印的日志如下:

可以发现环绕通知都完整执行了。

多个切面 

 这里我们介绍的是只有一个切面的情况,下面我们再来看一下多个切面的情况,这里我们在定义切面类CostTimeAdvice1,具体内容如下:

我们在来访问一下test01

日志如下:

通过日志可以发现,当存在多个切面时是按一种类似一种同心圆的顺序执行的,具体如下:


 通过图片可以发现目标方法外面被包裹了两层切面。

这两层切面的包裹顺序是可以自定义的。具体为通过给切面设置优先级,设置优先级就得使用@Order注解,这个注解可以给类设置优先级,当进行使用时优先使用优先级高的类。在@Order注解里需要设置一个数值,这个数值越小,类的优先级越高,反之。数越大,类的优先级越低。接下来我们来通过设置优先级来调整一下这两个切面的顺序:

然后我们来测试一下:

通过日志可以发现,切面的顺序果然被调整了。

通过上述对Spring AOP的使用我们可以总结出使用AOP有如下优点:

  • 在不侵入代码(也就是不修改原始代码)的前提下,对代码的功能进行增强(就是对目标方法进行拓展,例如我们的目标方法原本是不能记录执行时长的,通过切面就有记录时长的功能了)
  • 减少了重复的代码
  • 便于维护
  • 提高开发效率

 三、切点表达式

@pointcut

前面我们在定义切点时都得写一大长串,这样未免太麻烦,因此我们可以通过使用@pointcut注解来简化对切点的定义。

具体如下:

先写一个@pointcut注解,然后在注解里编写切点规则,然后再注解下定义一个方法,具体如下:

这样一个切点就设置好了。

如果我们要使用这个切点,直接在通知注解里引入这个方法即可:

excution表达式

excution表达式是一种常用的切点表达式,他用来表示一组规则,其语法如下:

excution(<访问限定符><返回类型> <包名.类名.方法名(方法参数)><异常>)  

通常情况下,访问限定符和异常可以被省略。前面我们使用的excution就进行了省略。excution支持使用正则表达式,正则表达式的语法如下:

  • ' * ' 表示任意一个字符串或者一个字符 ,因此可以用来表示包名,数据类型,类名,方法名等
  • ' . '表示任意一个字符,这个字符可以是一个普通字符,也可以是一个' * '
  • ’ ..'表示任意数量个 ‘ . '
@annotation表达式

使用excution表达式来定义切点其实存在一定缺陷,因为它是一组规则,只有符合规则的方法才能处理,但有时候我们所需要集中处理的方法并没有一个统一的规则,这时我们就需要使用@Annotation表达式了。使用这个注解的流程如下:

  1. 创建自定义注解
  2. 在需要集中处理的方法上加上该自定义注解
  3. 在通知上使用@annotation表达式

接下来我们来具体演示一下,首先我们创建一个@MyAspect注解(在new时选择@anonotation):

(大括号里还可以为注解设置一些属性,这里暂且不想去,就不设置了) 

然后我们在我们的test01方法上加一下这个注解

然后我们将切面所有通知注解都改为使用@annotation表达式:

然后我们通过浏览器来测试一下:

通过日志可以发现使用@annotation也成功设置好切点了。

Spring实现Aop的方式

最后我们在来看一个面试题:

Spring实现AOP的方式有哪些?

  • 基于@Aspect注解和excution表达式
  • 基于@Aspect和@annotation表达式
  • 基于Spring AOP的相关api(配置xml)
  • 基于代理

其中前面两种方式在上面的文章中已经演示过了,至于后面这两种方式这里就不介绍了,因为这两种方式已经逐渐过时,很少有人使用了。 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

❤️新版Linux零基础快速入门到精通——第三部分❤️

❤️新版Linux零基础快速入门到精通——第三部分❤️ 非科班的我&#xff01;Ta&#xff01;还是来了~~~3. Linux权限管控3.1 认知root用户3.1.1 Switch User——su3.1.2 sudo命令3.1.3 为普通用户配置sudo认证 3.2 用户和用户组3.2.1 用户、用户组3.2.2 用户组管理3.2.3 用户管…

YOLOv8-PySide --- 基于 ultralytics 8.1.0 发行版优化 | 代码已开源

YOLOv8-PySide — 基于 ultralytics 8.1.0 发行版优化 Github 项目地址&#xff1a;https://github.com/WangQvQ/Ultralytics-PySide6 BiliBili视频地址&#xff1a;https://www.bilibili.com/video 页面效果 如何使用 pip install ultralytics8.1.0 or git clone --branch v…

mysql基础3——创建和修改数据表

创建数据表 创建一个表&#xff08;importtype有默认值1&#xff09;并插入一条数据&#xff08;importtype字段没有指定值&#xff09; 约束 默认约束&#xff08;把设置的默认值自动赋值给字段&#xff09; create table demo.importhead(listnum int,supplied int,stock…

Vue3+antd:表格中合并多行相同数据

注&#xff1a;本次以合并相同ID为示例 首先获取远程数据&#xff0c;获取完成之后对数据进行遍历 let customCellList []; // {start:0,length:2,id:xx} // 如果接口返回的数据相同ID之间不相邻&#xff0c;需要手动排序后才可以实现合并效果 res.data.forEach((item, inde…

VBA运行后,为什么excel的三个工作表结果一样?

运行完了excel的三个工作表的结果一样&#xff0c;问题在哪呢&#xff1f; 代码如下&#xff1a; Sub 计算成绩() 计算成绩 Macro i为工作表行号 Dim i, m, total As Integer Dim w1 As Worksheet For m 1 To Worksheets.count Set w1 Worksheets(m) i 2 total 0 …

【电机控制】滑模观测器PMSM无感控制波形图

【电机控制】滑模观测器PMSM无感控制波形图 文章目录 前言一、FOC控制1.三相电流2.Clark变换静止坐标系iαiβ3.park变换旋转坐标系idiq4.电流环PI控制输出UdUq5.UdUq 反park变换UαUβ 二、反电动势观测器BEMF1.静止坐标系iαiβ提取反电动势EaEb2.反电动势EaEb提取位置信息、…

HarmonyOS开发案例:【视频播放器】

介绍 基于video、swiper和slider组件&#xff0c;实现简单的视频播放器&#xff0c;可支持海报轮播、视频播放等功能。 相关概念 [video组件]&#xff1a;视频播放组件。[swiper组件]&#xff1a;滑动容器&#xff0c;提供切换子组件显示的能力。[slider组件]&#xff1a;滑…

【Linux】破解工具John the Ripper和端口扫描工具NMAP

一、弱口令检测---John the Ripper 1.了解 John the Ripper John the Ripper 是一款开源的密码破解工具&#xff0c;可使用密码字典&#xff08;包含各种密码组合的列表文件&#xff09;来进行暴力破解。 一款密码分析工具&#xff0c;支持字典式的暴力破解通过对shadow文件…

什么是区块链?什么是X314协议?

X314协议是一种基于区块链技术的分布式账本协议&#xff0c;具有去中心化、安全性高和可扩展性强的特点。本文将从多个角度对X314协议进行通俗解释&#xff0c;带您了解这一前沿技术。 一、什么是区块链和分布式账本&#xff1f; 首先&#xff0c;我们需要了解什么是区块链和分…

使用JavaScript创建数组,并对其进行冒泡排序

JavaScript创建数组方式 字面量方式&#xff1a;使用方括号 [] 来创建数组&#xff0c;并在方括号内按顺序列出数组元素。 let arr [1, 2, 3, 4, 5]; Array() 构造函数方式&#xff1a;使用 new Array() 构造函数来创建数组&#xff0c;并传入数组元素作为参数。 let arr ne…

论文笔记:Large Language Models Are Zero-Shot Time Series Forecasters

2023 neurips 完全是零样本&#xff08;zero-shot&#xff09;的&#xff0c;不需要微调 1 方法 1.1 Tokenization&#xff08;分词和编码&#xff09; 现有的LLM&#xff08;比如GPT3&#xff09;的tokenizer不能直接用来编码时间序列的句子 比如对数字42235630&#xff0…

网络工程师----第九天

路由表解析 路由表&#xff1a;简单点说路由表就是路由器用于指导数据包如何转发的表项&#xff0c;记录了去往目的IP的下一跳去哪里。 路由&#xff1a;路由是网络中的基本概念&#xff0c;网络的基本功能就是使得处于网络中两个IP地址能够互相通信。 路由表作用&#xff1a…

【Java】变量零基础教程

目录 一、引言 二、基本组成单位 三、变量的基本原理 四、变量的基本使用步骤 五、变量快速入门 六、变量使用的注意事项 一、引言 为什么需要变量&#xff1f; ​​​​​​一个程序就是一个世界。 大家看下图&#xff0c;是我们现实中的一张生活照&#xff0c;图里有树…

sc2024项目consul

1. 什么是consul HashiCorp Consul是一款服务网络解决方案&#xff0c;可让团队管理服务之间以及内部部署和多云环境及运行时的安全网络连接。consul提供服务发现、服务治理、流量管理和对网络基础设施设备的自动更新。(添加链接描述)Consul使用Go语言开发 2. 功能 多数据中…

【ARM 裸机】模仿 STM32 驱动开发

1、修改驱动 对于 STM32 来说&#xff0c;使用了一个结构体将一个外设的所有寄存器都放在一起&#xff0c;在上一节的基础上进行修改&#xff1b; 1.1、添加清除 bss 段代码&#xff0c; 1.2、添加寄存器结构体 新建一个文件&#xff0c;命名imx6u.h&#xff0c;注意地址的连…

PLC_博图系列☞N=:在信号下降沿置位操作数

、 PLC_博图系列☞N&#xff1a;在信号下降沿置位操作数 文章目录 PLC_博图系列☞N&#xff1a;在信号下降沿置位操作数背景介绍N&#xff1a; 在信号下降沿置位操作数说明参数示例 关键字&#xff1a; PLC、 西门子、 博图、 Siemens 、 N 背景介绍 这是一篇关于PLC编程的…

【C++】---STL之vector详解

【C】---STL之vector详解 一、vector的介绍&#xff1a;二、vector的成员函数&#xff1a;1、vector类的构造函数2、vector的元素访问符3、vector的迭代器4、vector的模版5、vector的拷贝构造6、vector的容量&#xff08;1&#xff09;vector的增容机制&#xff08;2&#xff0…

学习笔记Day21:转录组差异分析

转录组差异分析 差异分析难点在于将数据处理成需要的格式 表达矩阵 数值型矩阵-count 行名是symbol 低表达量的基因需要过滤 分组信息 因子&#xff0c;对照组在level第一位 与表达矩阵的列一一对应 项目名称 字符串&#xff08;不要有特殊字符&#xff09; TCGA-XX…

IntelliJ IDEA - Lombok supports: OpenJDK javac, ECJ

问题描述 java: You arent using a compiler supported by lombok, so lombok will not work and has been disabled.Your processor is: com.sun.proxy.$Proxy26Lombok supports: OpenJDK javac, ECJ 解决方案 在 IDEA 设置中 File -> Settings 中找到配置如下&#xff1…

openEuler-23.03下载、安装

一、下载 下载地址&#xff1a;openEuler下载 | 欧拉系统ISO镜像 | openEuler社区官网 下载版本&#xff1a;openEuler-23.03-x86_64-dvd.iso 二、安装 cd /etc/sysconfig/network-scripts/ vi ifcfg-ens-33## 要修改部分 BOOTPROTOstatic## 新增部分 IPADDR192.168.1.128 …