【JavaEE】Spring AOP (面向切面)详解

article/2025/9/21 14:40:28

目录:

  • 1. 什么是 Spring AOP?
    • 1.1 AOP
    • 1.2 使用 AOP 的场景
  • 2. AOP 组成
    • 2.1 切面(Aspect)
    • 2.2 连接点(Join Point)
    • 2.3 切点(Pointcut)
    • 2.4 通知(Advice)
  • 3. AOP 概念举列
  • 4. Spring AOP 实现
    • 4.1 添加 spring AOP 框架支持
    • 4.2 定义切面和切点
      • 4.2.1 AspectJ 表达式语法说明
    • 4.3 定义相关通知(实现通知方法)
      • 4.3.1 前置通知 @Before + 后置通知 @After
      • 4.3.2 返回之后通知 @AfterReturning + 抛异常后通知 @AfterThrowing:
      • 4.3.3 环绕通知 @Around (统计对应类下每个方法的执行时间)
  • 5. Spring AOP 实现原理(了解即可)
    • 5.1 织入(Weaving):代理的生成时机 -- 运行期
    • 5.2 动态代理
    • 5.3 JDK 和 CGLIB 实现的区别

1. 什么是 Spring AOP?

Spring AOP 与 AOP 就如果 IOC(思想:控制反转) 和 DI (具体实现:依赖注入) ,其中AOP是思想,Spring AOP是具体实现。

AOP 是⼀种思想, Spring AOP 是⼀个框架,提供了⼀种对 AOP 思想的实现。

1.1 AOP

AOP(Aspect Oriented Programming):⾯向切⾯编程,它是⼀种思想,它是对某⼀类事情的集中处理

AOP:面向切面编程,与OOP(面向对象编程)类似但又不互斥,可以说AOP是OOP的一种拓展与补充。

⽐如⽤户登录权限的效验,没用 AOP 之前,我们所有需要判断⽤户登录的⻚⾯(中的⽅法),都要各⾃实现或调⽤⽤户验证的⽅法,然⽽有了 AOP 之后,我们只需要在某⼀处配置⼀下,所有需要判断⽤户登录⻚⾯(中的⽅法)就全部可以实现用户登录验证了,不再需要每个⽅法中都写相同的⽤户登录验证了。

1.2 使用 AOP 的场景

如在判断用户是否登录的场景中,一个网站项目中,除了登录和注册这两个页面不用判断用户登录状态,此外的诸多页面都需要使用同样的方式来判断用户是否登录,这些判断方法都是相同的,这么多的方法就会增加代码的维护和修改的成本;

对于这种功能的统一,且使用的地方较多的功能,就可以考虑 AOP 来进行统一处理了。

除了统⼀的⽤户登录判断之外,AOP 还可以实现:

  • 统⼀⽇志记录
  • 统⼀⽅法执⾏时间统计
  • 统⼀的返回格式设置
  • 统⼀的异常处理
  • 事务的开启和提交等

也就是说使⽤ AOP 可以扩充多个对象的某个能⼒,所以 AOP 可以说是 OOP(Object OrientedProgramming,⾯向对象编程)的补充和完善。

2. AOP 组成

AOP 组成的官方概念很难理解,这里给出官网解释(不加粗)和博主个人理解解释(加粗)

2.1 切面(Aspect)

切⾯(Aspect)由切点(Pointcut)和通知(Advice)组成,它既包含了横切逻辑的定义,也包括了连接点的定义。

切面:定义 AOP 是针对哪个统一的功能的,这个功能就叫做一个切面,比如用户登录功能或方法的统计日志,他们就各是一个切面。切面是由 切点 +通知 组成的。切⾯是包含了:通知、切点和切⾯的类,相当于 AOP 实现的某个功能的集合。

2.2 连接点(Join Point)

应⽤执⾏过程中能够插⼊切⾯的⼀个点,这个点可以是⽅法调⽤时,抛出异常时,甚⾄修改字段时。切⾯代码可以利⽤这些点插⼊到应⽤的正常流程之中,并添加新的⾏为。

连接点:所有可能触发 AOP (拦截方法的点) 就称为连接点;连接点相当于需要被增强的某个 AOP 功能的所有方法。

2.3 切点(Pointcut)

Pointcut 是匹配 Join Point 的谓词。

Pointcut 的作⽤就是提供⼀组规则(使⽤ AspectJ pointcut expression language 来描述)来匹配 Join Point,给满⾜规则的 Join Point 添加 Advice。

切点:用来定义 AOP 拦截的规则的 ;切点相当于保存了众多连接点的⼀个集合(如果把切点看成⼀个表,而连接点就是表中⼀条⼀条的数据)。

2.4 通知(Advice)

切⾯也是有⽬标的 ——它必须完成的⼯作。在 AOP 术语中,切⾯的⼯作被称之为通知。

通知:定义了切⾯是什么,何时使⽤,其描述了切⾯要完成的⼯作,还解决何时执⾏这个⼯作的问题。

通知:规定 AOP 执行的时机和执行的方法;

Spring 切⾯类中,可以在⽅法上使⽤以下注解,会设置⽅法为通知⽅法,在满⾜条件后会通知本⽅法进⾏调⽤:

  • 前置通知使用 @Before:通知⽅法会在⽬标⽅法调⽤之前执⾏。

  • 后置通知使用 @After:通知⽅法会在⽬标⽅法返回或者抛出异常后调⽤。

  • 返回之后通知使用 @AfterReturning:通知⽅法会在⽬标⽅法返回后调⽤。

  • 抛异常后通知使用 @AfterThrowing:通知⽅法会在⽬标⽅法抛出异常后调⽤。

  • 环绕通知使⽤ @Around:通知包裹了被通知的⽅法,在被通知的⽅法通知之前和调用之后执行自定义的行为。

  • 通知相当于要增强的方法

3. AOP 概念举列

AOP 整个组成部分的概念如下图所示,以多个页面都要访问⽤户登录权限为例:
在这里插入图片描述

4. Spring AOP 实现

这节博主用 Spring AOP 来实现⼀下 AOP 的功能,完成的⽬标是拦截所有 UserController ⾥⾯的⽅法,每次调⽤ UserController 中任意⼀个⽅法时,都执⾏相应的通知事件。

实现步骤如下:

4.1 添加 spring AOP 框架支持

在 maven 中央仓库中搜索 spring aop,,选择如图所示第二个:
选择一个次新版本(考虑稳定),点进去:
在这里插入图片描述
在 pom.xml 中添加如下配置:
在这里插入图片描述

!-- https://mvnrepository.com/artifact/org.springframework.boot/springboot-starter-aop -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

4.2 定义切面和切点

切面指的是具体要处理的某⼀类问题,⽐如⽤户登录权限验证就是⼀个具体的问题;
Spring AOP 切面的定义如下,在切面中我们要定义拦截的规则(切点),具体实现如下:在这里插入图片描述

这里切点的定义使用的是 AspectJ 表达式语法

其中 pointcut ⽅法为空⽅法,它不需要有⽅法体,此⽅法名就是起到⼀个“标识”的作⽤,标识下⾯的通知⽅法具体指的是哪个切点(因为切点可能有很多个)。

4.2.1 AspectJ 表达式语法说明

AspectJ ⽀持三种通配符:

*:表示匹配任意的内容,用在返回值,包名,类名,方法名都可以使用
…:匹配任意字符,可以使用在方法参数上,如果用在类上需要配合 * 一起使用
+:表示匹配指定类及其它底下的所有子类,比如 com.Car+ 表示匹配Car 及其所有的子类

在这里插入图片描述

切点表达式由切点函数组成,其中 execution() 是最常⽤的切点函数,⽤来匹配⽅法,语法为:

execution(<修饰符><返回类型><包.类.⽅法(参数)><异常>)
(修饰符和异常可以省略)

表达式示例:
在这里插入图片描述

4.3 定义相关通知(实现通知方法)

通知定义的是被拦截的⽅法具体要执⾏的业务,⽐如⽤户登录权限验证⽅法就是具体要执⾏的业务。

Spring AOP 中,可以在⽅法上使⽤以下注解,会设置⽅法为通知⽅法,在满⾜条件后会通知本⽅法进⾏调⽤:

  • 前置通知使⽤@Before:通知⽅法会在⽬标⽅法调⽤之前执⾏。
  • 后置通知使⽤@After:通知⽅法会在⽬标⽅法返回或者抛出异常后调⽤。
  • 返回之后通知使⽤@AfterReturning:通知⽅法会在⽬标⽅法返回后调⽤。
  • 抛异常后通知使⽤@AfterThrowing:通知⽅法会在⽬标⽅法抛出异常后调⽤。
  • 环绕通知使⽤@Around:通知包裹了被通知的⽅法,在被通知的⽅法通知之前和调⽤之后执⾏⾃定义的⾏为。

具体实现如下:
usercontroller 类下方法如下:
在这里插入图片描述

4.3.1 前置通知 @Before + 后置通知 @After

前置通知:
在这里插入图片描述
后置通知:
在这里插入图片描述
在设置了前置通知和后置通知的情况下,访问方法:
在这里插入图片描述
可以看出,前置通知与后置通知分别在方法执行之前和之后进行执行。

4.3.2 返回之后通知 @AfterReturning + 抛异常后通知 @AfterThrowing:

在这里插入图片描述
此时在代码中触发一个被除数为0的异常:
在这里插入图片描述

在这里插入图片描述
可以看出 先执行前置通知,在方法抛出异常后,抛异常后通知@AfterThrowing 执行,接着再执行后置通知;

如果正常放回,则是:
在这里插入图片描述
在这里插入图片描述

先执行前置通知,在方法正常返回后,返回之后通知 @AfterReturning执行,接着再执行后置通知;

4.3.3 环绕通知 @Around (统计对应类下每个方法的执行时间)

环绕通知博主以实现 记录方法所执行的时间 的需求来举列:
具体实现细节如下:
在这里插入图片描述
加上前面的调整,访问方法结果如下:
在这里插入图片描述
使用以上的注解就能实现 spring AOP 啦 ~

5. Spring AOP 实现原理(了解即可)

Spring AOP 是通过动态代理的⽅式,在运行期将 AOP 代码织入到程序中的,它的实现⽅式有两种:JDK ProxyCGLIB,这两种实现动态代理的方式均使用到了 反射 的知识。

Spring AOP 是构建在动态代理基础上,因此 Spring 对 AOP 的⽀持局限于⽅法级别的拦截。(功能的最小实现就是方法)

Spring AOP ⽀持 JDK ProxyCGLIB Proxy ⽅式实现动态代理。
默认情况下,实现了接⼝的类,使⽤AOP 会基于 JDK ⽣成代理类,没有实现接⼝的类,会基于 CGLIB ⽣成代理类。
在这里插入图片描述

5.1 织入(Weaving):代理的生成时机 – 运行期

织⼊是把切⾯应⽤到⽬标对象并创建新的代理对象的过程,切⾯在指定的连接点被织⼊到⽬标对象中。

在⽬标对象的⽣命周期⾥有多个点可以进⾏织⼊:

  • 编译期:切⾯在⽬标类编译时被织⼊。这种⽅式需要特殊的编译器。AspectJ的织⼊编译器就是以这种⽅式织⼊切⾯的。
  • 类加载器:切⾯在⽬标类加载到JVM时被织⼊。这种⽅式需要特殊的类加载器(ClassLoader),它可以在⽬标类被引⼊应⽤之前增强该⽬标类的字节码。AspectJ5的加载时织⼊(load-time weaving. LTW)就⽀持以这种⽅式织⼊切⾯。
  • 运⾏期:切⾯在应⽤运⾏的某⼀时刻被织⼊。⼀般情况下,在织⼊切⾯时,AOP容器会为⽬标对象动态创建⼀个代理对象。SpringAOP就是以这种⽅式织⼊切⾯的。

5.2 动态代理

此种实现在设计模式上称为动态代理模式,在实现的技术⼿段上,都是在 class 代码运⾏期,动态的织⼊字节码。

Spring AOP,主要基于两种⽅式:JDK 及 CGLIB 的⽅式。这两种⽅式的代理⽬标都是被代理类中的⽅法,在运⾏期,动态的织⼊字节码⽣成代理类。

  • CGLIB是Java中的动态代理框架,主要作⽤就是根据⽬标类和⽅法,动态⽣成代理类。
  • Java中的动态代理框架,⼏乎都是依赖字节码框架(如 ASM,Javassist 等)实现的。
  • 字节码框架是直接操作 class 字节码的框架。可以加载已有的class字节码⽂件信息,修改部分信息,或动态⽣成⼀个 class。

5.3 JDK 和 CGLIB 实现的区别

  1. JDK 实现,要求被代理类必须实现接⼝,之后是通过 InvocationHandler 及 Proxy,在运⾏时动态的在内存中⽣成了代理类对象,该代理对象是通过实现同样的接⼝实现(类似静态代理接⼝实现的⽅式),只是该代理类是在运⾏期时,动态的织⼊统⼀的业务逻辑字节码来完成。
  2. CGLIB 实现,被代理类可以不实现接口,是通过继承被代理类,在运⾏时动态的⽣成代理类对象。(final修饰的最终类不能被继承,也就不能使用 CGLIB 实现动态代理,只能通过 JDK 实现)
  • Spring AOP over ✨~

http://chatgpt.dhexx.cn/article/R2XuP1WL.shtml

相关文章

斜杠,反斜杠说明

/ 斜杠 \反斜杠 在window中都用斜杠 反斜杠是用来转译字符串的 eg: \"a\" 输出"a"

斜杠、反斜杠、双斜杠、反双斜杠的区别和使用方法及范围

背景 这边我就找了两篇大神写的文章&#xff0c;讲得非常清晰明了。文章主要讲了一些历史缘故和我们面对各种斜杠时的疑惑。 斜杠’/’ 和反斜杠’’ 深入探讨正斜杠和反斜杠 概念 1. 斜杠"/"是URL地址中用到的分隔符&#xff0c;并且在linux系统中的文件路径也是…

glob.glob()之返回路径的正反斜杆问题

Windows环境下用一个反斜杠就行 绝对路径&#xff1a;D:\PyCharm_code\pytorch_study\xxx 相对路径&#xff1a;.\cifar10_train\**\*.png 以下是踩过的坑&#xff1a;记录下

正反斜杠的区别_正斜杠( / )和反斜杠( \ )的区别

反斜杠“\”是电脑出现了之后为了表示程序设计里的特殊含义才发明的专用标点。所以除了程序设计领域外&#xff0c;任何地方都不应该使用反斜杠。 如何区分正反斜杠 英语&#xff1a;"/" 英文是forward slash, “\" 是backward slash 形象些比喻的话&#xff0c…

正斜杠 “/” 与反斜杠 “\”辨析

文章目录 1. 正斜杠 / / /2. 反斜杠 \ \backslash \3. 正斜杠与反斜杠的区别4. 注意 注意&#xff0c; / / / 为正斜杠(forward slash)&#xff0c;而 \ \backslash \ 为反斜杠(backward slash)。 1. 正斜杠 / / / 斜线是斜线标点符号 / / /。曾经用于标记句点和逗号的斜…

斜杠'/' 和反斜杠'\'

斜杠’/‘和反斜杠’\’ 2019-1-21 引言&#xff1a;从大一进入信息专业&#xff0c;正式接触计算机、代码也有几年了。一开始迷迷糊糊学Ascii码&#xff0c;很多特殊字符都需要转义&#xff0c;比如换行符\n&#xff0c;自那时起我就拎不清转义符是斜杠还是反斜杠&#xff0c;…

全面了解 Python 中的反斜杆

本文全面介绍了 Python 中反斜杆(\)的用法&#xff0c;包括原始字符串和普通字符串&#xff0c;repr() 和 str() ,\ 作为转义符&#xff0c;\ 作为续行符&#xff0c;\ 在字符串转义和正则表达式转义中的过程及注意事项等。阅读本文预计 6 min. 全面了解 Python 中的反斜杆 1. …

教你认识正斜杠(/)与反斜杠(\)

正斜杠&#xff0c;又称左斜杠&#xff0c;符号是 “/” ; 反斜杠&#xff0c;也称右斜杠&#xff0c;符号是 “” 。 经常很迷惑正斜杠与反斜杠到底有何区别&#xff1f;以下是一些总结: 背景了解 &#xff1a; DOS路径&#xff1a; C:\WINDOWS\SETTING …这是反斜杠的作用后…

微信支付,二维码图片解析

微信支付&#xff1a; 后台返回的是数据流&#xff1b; 开始这样&#xff0c;但是不行&#xff0c; 解决&#xff1a;在请求里面加入 ‘responseType’: ‘blob’ , 转换&#xff1a;附上base64转图片 //base64转换base64ImgtoFile(dataurl, filename file) {let arr data…

Apache里如何将图片解析成PHP

首先&#xff0c;如果没有安装PHP&#xff0c;先安装PHP yum install -y php然后进入网站根目录&#xff0c;如果不记得网站根目录&#xff0c;可以去配置文件里找 我的是/mnt/z 所以进入这个目录下&#xff0c;新建一个i.jpg文件 在浏览器里查看这个文件&#xff0c;存在错误…

图像解析力算法—SFR(Spatial Frequency Response)

Mitre SFR 1.4和sfrmat3是基于ISO 12233标准&#xff0c;但在某些方面彼此不同&#xff1a;Mitre SFR 1.4旨在尽可能接近标准&#xff0c; 而sfrmat3包含一些改进&#xff0c;可以获得精确的结果 即使被测试的图像质量极低。 M O R E MTF50&#xff0c;MTF50P 在表示相机图像…

JPEG图像格式解析

参考链接&#xff1a;jpeg图片格式详解_460833359的博客-CSDN博客_jpg文件通常是什么 一、JPEG图像介绍 jpg/jpeg是24位的图像文件格式&#xff0c;也是一种高效率的压缩格式&#xff0c;文件格式是JPEG&#xff08;联合图像专家组&#xff09;标准的产物&#xff0c;是面向连…

图像解析力算法—SFR(Spatial Frequency Response)概念理解

最近这一个月在搞SFR算法--&#xff08;空间频域响应&#xff09;&#xff0c;终于也算是搞出来了&#xff0c;网上关于SFR计算MTF的资料和博客也是比较少&#xff0c;现在就是总结一下&#xff0c;也算是方便后人&#xff0c;篇幅估计会比较长&#xff0c;会分篇慢慢写。 讲到…

DXF解析CAD图形解析PLT格式文件解析C#工程源码

DXF解析CAD图形解析PLT格式文件解析C#工程源码 激光切割机 雕刻机 打标机 写字机 巡边机 1.在文件菜单中选择打开dxf文件&#xff0c;算法会自动解析图形 2.解析完成后自动还原图形在界面显示 3.图形中的线条左边自动保存&#xff0c;在界面右侧工具栏选择开始加工按钮&…

Base64在线解析,编码转化为图片

博主介绍&#xff1a; 22届计科专业毕业&#xff0c;来自湖南&#xff0c;主要是在CSDN记录一些自己在Java开发过程中遇到的一些问题&#xff0c;欢迎大家一起讨论学习&#xff0c;也欢迎大家的批评指正。 前言 虽然我自己Base64在线解析用的少&#xff0c;但是避免不了需要使用…

前端xmp-js解析图片xmp信息

功能介绍 前端有Exif.js用于解析图像基础信息&#xff0c;但是对于一些比较特殊的图像信息&#xff0c;例如大疆无人机所拍摄得到的图像&#xff0c;它会在图像中添加xmp信息用来保存设备的一些额外信息&#xff0c;例如朝向等等。xmp-js就是一个可以用来解析图片xmp信息的第三…

stegsolve图片隐写解析器的使用

layout: post title: “ctf-隐写图片解析器-stegsolve的使用” categories: [ctf] tags: [stegsolve] CTF隐写术————隐写图片解析神器----stegsolve stegsolve下载地址&#xff1a;http://www.caesum.com/handbook/Stegsolve.jar stegsolve安装配置&#xff1a;配置好Jav…

前端图片信息解析Exif.js

图片信息解析Exif.js 功能说明 Exif.js适用于利用JavaScript读取图像的原始数据的功能扩展&#xff0c;例如&#xff1a;拍照方向、相机设备型号、拍摄时间、ISO感光度、GPS地理位置等数据。 功能实现 API方法 Exif.getAllTags(file) exif.getData(file, () > {const …

java根据照片原图解析经纬度位置信息

有很多伙伴说不行&#xff0c;***必须是拍照原图***才行 1.pom坐标 <dependency><groupId>com.drewnoakes</groupId><artifactId>metadata-extractor</artifactId><version>2.6.2</version></dependency>2.测试代码 package…

微信小程序 + vant组件van-card 图片解析不到

在使用vant组件制作微信小程序项目时&#xff0c;遇到了图片解析不到的问题。 场景如下&#xff1a; 在页面中&#xff0c;应用了vant组件库中的van-card,组件中将图片路径传给van-card中的thumb属性&#xff0c;即可在左侧位置显示出图片&#xff0c;目标效果如下&#xff1…