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)
  • 基于代理

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

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

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

相关文章

二叉树之AVL树

文章目录 1. AVL树的概念&#xff08;logN)1.1背景1.2规则 2.AVL树节点的定义3.AVL树的插入4. AVL树的旋转(重点&#xff09;4.1 新节点插入较高的右子树的右侧&#xff1a;左单璇&#xff1b;4.2 新节点插入较高左子树的左侧&#xff1a;右单璇&#xff1b;4.3&#xff08;双旋…

Axure引用ECharts图表 解决火狐浏览器出错

Axure原型添加Echarts图表&#xff0c;没耐心看文章的可以直接下载示例 Axure中使用ECharts图表示例 1. 打开Axure新建页面 2. 页面添加元件 元件类型随意&#xff0c;矩形、动态面板、热区、图片 甚至段落都可以3. 命名元件 随意命名&#xff0c;单个页面用到多个图表时名…

【读书笔记】 针对ICS的ATTCK矩阵详解(二)

三、持续控制&#xff08;Persistence&#xff09; 该阶段&#xff1a;攻击者试图在您的 ICS 环境中保持其立足点。 持久性包括攻击者用来在重启、更改凭据和其他可能切断其访问的中断时保持对 ICS 系统和设备的访问的技术。用于持久性的技术包括任何访问、操作或配置更改&…

imx6ull设备树驱动--pinctl、ioctl

添加pinctl节点 进入arch/arm/boot/dts目录下dts文件 在iomuxc下添加pinctlled节点 将 GPIO1_IO03 这个 PIN 复用为 GPIO1_IO03&#xff0c;电气属性&#xff08;配置GPIO一些列寄存器&#xff09;值为 0X10B0 添加led设备节点 与上一节一样&#xff0c;在 / 下面添加设备节…

知攻善防应急靶场-Windows(Web1-2-3)

知攻善防应急靶场-Web1 1.要求 2.过程 直接扫网站根目录 发现后门 <?php error_reporting(0); session_start();$key"e45e329feb5d925b"; //该密钥为连接密码32位md5值的前16位&#xff0c;默认连接密码rebeyond$_SESSION[k]$key;session_write_close();$postf…

Pytest精通指南(24)钩子函数-随机执行(pytest-random-order)

文章目录 前言应用场景插件安装参数分析使用方法 前言 pytest-random-order 是一个pytest插件&#xff0c;用于在每次运行测试套件时随机化测试用例的执行顺序。 它可以帮助识别和避免依赖于特定测试执行顺序的问题&#xff0c;从而提高测试的健壮性和可靠性。 应用场景 测试无…

遇到you-get下载报错问题解决

pip3 install you-get安装这里就不赘述了&#xff0c;如果你还不会安装&#xff0c;说明这篇文章不适合你&#xff0c;这篇文章主要解决当执行you-get的报错&#xff1a; 当然你可以加选项–debug具体看一下到底报什么错。 第一步 替换文件 首先&#xff0c;我们下载仓库最新…

https协议的加密方式详解

各位大佬能多多点赞关注评论收藏&#xff0c;球球各位大佬们了&#xff01;&#xff01; &#xff01; 目录 1.为什么要加密&#xff1f; 2.如何加密 1.密钥&#xff08;yue,第四声&#xff09; 2.对称加密 3.非对称加密 4.公证机构 3.总结 1.为什么要加密&#xff1f;…

探索通过GPT和云平台搭建网安实战培训环境

项目背景 网络安全是一个不断演变的领域&#xff0c;面临着日益复杂的挑战和不断扩大的威胁。数字化时代&#xff0c;随着勒索攻击、数据窃取、网络钓鱼等频频出现&#xff0c;网络攻击的威胁指数和影响范围进一步增加&#xff0c;如何防范网络攻击&#xff0c;确保数据安全&a…

共享内存和信号灯集练习

#include <mystdio.h> int main(int argc, const char *argv[]) { //创建key值 key_t key ftok("/home/ubuntu",2); if(key<0) { perror("ftok"); return -1; } printf("key%#x\n",key); …

什么是0-day漏洞,怎么防护0-day漏洞攻击

随着信息技术的快速发展&#xff0c;网络安全问题日益凸显&#xff0c;其中0day漏洞攻击作为一种高级威胁手段&#xff0c;给企业和个人用户带来了极大的风险。下面德迅云安全就对0day漏洞攻击进行简单讲解下&#xff0c;并分享相应的一些安全措施&#xff0c;以期提高网络安全…

开源项目-汽车租赁管理系统

哈喽,大家好,今天主要给大家带来一个开源项目-汽车租赁管理系统 汽车租赁管理系统的主要功能包括汽车管理,新闻管理,用户管理,订单管理,数据展示等模块 注:后续文章都会附上安装教程,有问题也欢迎大家评论私信。 登录 汽车管理 汽车管理可以查看所有汽车进行线上汽…