Spring AOP 的本质,是在 Bean 创建阶段,通过动态代理技术,对目标对象进行增强,在不修改原有业务代码的情况下,统一织入横切逻辑。
文章目录
- 一、为什么要用AOP?(使用场景)
- 二、SpringAOP的核心组成
- 三、AOP的核心流程
-
-
- [1. 在Bean创建阶段动手](#1. 在Bean创建阶段动手)
- [2. 关键角色 :BeanPostProcessor](#2. 关键角色 :BeanPostProcessor)
-
- [四、Spring AOP 的两种代理方式(必问)](#四、Spring AOP 的两种代理方式(必问))
-
-
- [1. JDK动态代理](#1. JDK动态代理)
- [2. CGLIB动态代理](#2. CGLIB动态代理)
-
- 五、方法调用时发生了什么?
- 六、事务是AOP的经典落地案例
一、为什么要用AOP?(使用场景)
想象一个典型业务:
java
下单()
校验参数
打日志
校验权限
开启事务
核心业务
提交事务
问题来了👇
-
日志、事务、权限 到处都有
-
改一次,要改一堆类
-
业务代码被"杂音"淹没
于是 Spring 说:
👉 这些"横着切进业务"的逻辑,交给 AOP 管
这些就是 横切关注点(Cross-Cutting Concerns):
-
事务
-
日志
-
权限
-
监控
-
接口幂等
二、SpringAOP的核心组成
| 概念 | 作用 |
|---|---|
| Aspect(切面) | 封装横切逻辑的类 |
| Advice(通知) | 具体增强逻辑(方法) |
| Pointcut(切点) | 决定拦截哪些方法 |
| JoinPoint(连接点) | 被拦截的方法 |
| Target(目标对象) | 原始业务对象 |
| Proxy(代理对象) | Spring 返回给你的对象 |
| 一句话串起来👇 |
切面 = 切点 + 通知,Spring 用代理对象替代目标对象执行方法
三、AOP的核心流程
1. 在Bean创建阶段动手
Spring AOP 不是运行时随便插的,而是在:
Bean 初始化完成后,放入 IOC 容器之前
流程简化版:
csharp
Bean 实例化
↓
属性注入
↓
初始化(init)
↓
👉 AOP 判断是否需要代理
↓
生成代理对象
↓
放入 IOC 容器
所以你从容器里拿到的对象,已经是代理对象了。
2. 关键角色 :BeanPostProcessor
Spring AOP 的入口是:
AbstractAutoProxyCreator(Bean 后置处理器)
它干的事只有一句话:
判断当前 Bean 是否匹配切点,如果匹配,就创建代理对象
四、Spring AOP 的两种代理方式(必问)
1. JDK动态代理
条件 :目标类 实现了接口
原理:
-
基于
InvocationHandler -
代理的是 接口方法
java
Proxy.newProxyInstance(...)
特点:
-
只能代理接口
-
生成代理类快
-
Spring 默认优先使用
2. CGLIB动态代理
条件:
-
没有接口
-
或强制使用
proxyTargetClass = true
原理:
-
继承目标类
-
通过 方法拦截器(MethodInterceptor)
特点:
-
代理的是类
-
不能代理
final方法 -
性能在现代 JVM 下已非常接近 JDK 代理
五、方法调用时发生了什么?
当你调用代理对象的方法:
scss
代理对象.method()
↓
拦截器链(Interceptor Chain)
↓
@Before
↓
@Around(前)
↓
目标方法
↓
@Around(后)
↓
@After
↓
@AfterReturning / @AfterThrowing
本质是一个 责任链模式。
六、事务是AOP的经典落地案例
java
@Transactional
public void save() {
// 业务代码
}
Spring 干了什么?
-
解析
@Transactional -
生成事务切面
TransactionInterceptor -
方法前:
- 开启事务
-
方法后:
-
正常 → 提交
-
异常 → 回滚
-
👉 事务本质 = AOP + 拦截器