Spring AOP 详解:面向切面编程的核心与实践
1. 什么是 AOP?
AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,旨在将横切关注点(如日志记录、事务管理、权限校验等)从业务逻辑中分离出来,以提高代码的模块化和可维护性
在 Spring 框架中,AOP 通过代理模式实现,允许开发者在不修改原有代码的情况下,动态地将额外行为织入到目标方法中
2. AOP 的核心概念
-
Aspect(切面):横切关注点的模块化实现。例如,日志记录、事务管理等。
-
Join Point(连接点):程序执行过程中的某个点,如方法调用或异常抛出。
-
Advice(通知)
:在连接点执行的动作。Spring 支持以下通知类型:
- Before:在目标方法执行前执行。
- After:在目标方法执行后执行,无论是否抛出异常。
- AfterReturning:在目标方法成功返回后执行。
- AfterThrowing:在目标方法抛出异常后执行。
- Around:环绕目标方法执行,可以控制是否执行目标方法(最重要)
- 环绕通知必须依赖形参
ProceedingJoinPoint
才能实现对原始方法的调用,进而实现原始方法调用钱前后同时添加通知 - 通知中如果未使用
ProceedingJoinPoint
对原始方法进行调用将跳过原始方法的执行 - 对原始方法的调用可以不接收返回值,通知方法设置成
void
即可,如果接收返回值,必须设定为Object
类型 - 原始方法的返回值如果是
void
类型,通知方法的返回值类型可以设置成void
,也可以设置成Object
- 由于无法预知原始方法运行是否会抛出异常,因此环绕通知方法必须抛出
Throwable
对象
- 环绕通知必须依赖形参
-
Pointcut(切点):用于匹配连接点的表达式,决定哪些方法会被拦截
-
Weaving(织入):将切面应用到目标对象并创建代理对象的过程
-
目标对象(Target):被代理的类
-
代理(Proxy):AOP 通过动态代理来增强目标对象
3. Spring AOP 的实现方式
Spring AOP 支持两种实现方式:
- 基于代理的 AOP:通过 JDK 动态代理或 CGLIB 生成代理对象
- 基于注解的 AOP:使用
@Aspect
注解定义切面
4. 代码示例
以下是一个基于注解的 Spring AOP 示例,实现日志记录功能。
4.1 添加依赖
在 pom.xml
中添加 Spring AOP 依赖:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.14</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.22.1</version>
</dependency>
<!-- Spring Test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>6.1.14</version>
<scope>test</scope>
</dependency>
<!-- JUnit 5 -->
<dependency