构建 AOP 拦截器链是 Spring AOP 实现横切逻辑的核心流程,其本质是将多个切面(Aspect)的通知(Advice)按特定顺序组织成链式结构,在目标方法执行的前后动态拦截并执行这些逻辑。以下从核心组件、构建流程、执行顺序三个维度深度解析,并结合源码说明其工作机制。
一、AOP 拦截器链的核心组件
拦截器链的构建依赖以下核心组件,理解它们的职责是解析流程的基础:
1. Advisor(通知器)
Advisor 是 Spring AOP 的核心接口,定义了“何时(Pointcut)”和“如何(Advice)”执行横切逻辑。每个 Advisor 包含一个 Pointcut
(切点)和一个 Advice
(通知)。
- Pointcut:匹配需要拦截的方法(如
execution(* com.example.service.*.*(..))
)。 - Advice:具体的横切逻辑(如
@Before
、@After
、@Around
等通知类型)。
2. Advice(通知)
Advice 是拦截器链中的“执行单元”,根据其在目标方法执行周期中的位置分为以下类型:
通知类型 | 执行时机 | 特点 |
---|---|---|
@Before | 目标方法执行前 | 无法阻止目标方法执行(除非抛出异常)。 |
@After | 目标方法执行后(无论成功或异常) | 无法获取目标方法返回值。 |
@AfterReturning | 目标方法成功返回后 | 可获取目标方法返回值(通过 returning 属性绑定)。 |
@AfterThrowing | 目标方法抛出异常后 | 可获取异常对象(通过 throwing 属性绑定)。 |
@Around | 包裹目标方法执行(可控制是否继续执行目标方法) | 可获取目标方法参数、返回值、异常,是功能最强大的通知类型。 |
3. ProxyFactory(代理工厂)
ProxyFactory 是 Spring AOP 中生成代理对象的核心类,负责:
- 管理目标对象(Target)。
- 收集所有匹配的 Advisor(拦截器)。
- 生成代理对象(JDK 或 CGLIB)。
4. Advised(代理配置)
Advised 是 ProxyFactory 的内部接口,定义了代理的配置信息(如拦截器链、是否暴露代理等)。其实现类(如 AdvisedSupport
)负责实际管理拦截器链。
二、拦截器链的构建流程
拦截器链的构建是一个动态组装过程,发生在 Spring 容器初始化或首次访问代理对象时。以下是关键步骤(结合源码):
1. 扫描切面并收集 Advisor
Spring 容器启动时,通过 BeanPostProcessor
(如 AnnotationAwareAspectJAutoProxyCreator
)扫描所有被 @Aspect
标记的切面类,提取其中的 @Pointcut
、@Before
、@After
等注解,生成对应的 Advisor
对象。
源码关键逻辑(简化自 AnnotationAwareAspectJAutoProxyCreator
):
public class AnnotationAwareAspectJAutoProxyCreator extends AbstractAutoProxyCreator {
@Override
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 扫描切面,收集所有 Advisor
List<Advisor> advisors = findEligibleAdvisors(bean.getClass(), beanName);
if (!advisors.isEmpty()) {
// 生成代理对象
return createProxy(bean.getClass(), beanName, advisors, new SingletonTargetSource(bean));
}
return bean;
}
private List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 通过 AspectJ 表达式解析器,匹配所有符合条件的 Advisor
List<Advisor> allAdvisors = new ArrayList<>();
// 1. 收集所有 @Pointcut 定义的切点
// 2. 收集所有 @Before/@After 等通知对应的 Advisor
// 3. 过滤掉不匹配当前 bean 的 Advisor(通过 Pointcut 匹配)
return allAdvisors;
}
}
2. 排序 Advisor(可选)
若多个 Advisor 存在,可通过 @Order
注解或 Ordered
接口指定执行顺序(数值越小优先级越高)。未显式指定时,默认按切面类在类路径中的加载顺序排序。
3. 构建拦截器链
ProxyFactory 将收集到的 Advisor 转换为 Interceptor
链。每个 Advisor
对应一个 Interceptor
(如 MethodBeforeAdviceInterceptor
、AroundAdviceInterceptor
),链的顺序由 Advisor 的排序决定。
关键类:
AdvisedSupport
:管理拦截器链的核心类,内部通过List<Advisor>
存储所有通知器。InterceptorAndDynamicMethodMatcher
:包装Advisor
和动态匹配逻辑(如@Pointcut
的动态匹配)。
4. 生成代理对象
根据目标对象是否实现接口,ProxyFactory 选择生成 JDK 动态代理或 CGLIB 代理。代理对象的 InvocationHandler
(JDK)或 MethodInterceptor
(CGLIB)会持有拦截器链,并在方法调用时触发拦截逻辑。
三、拦截器链的执行流程
当目标方法被调用时,代理对象会触发拦截器链的执行。以下是典型的执行顺序(以 @Around
通知为例):
1. 调用代理对象的方法
客户端通过代理对象调用目标方法(如 userService.createUser()
)。
2. 触发拦截器链
代理的 InvocationHandler
(JDK)或 MethodInterceptor
(CGLIB)捕获方法调用,开始执行拦截器链。
3. 按顺序执行拦截器
拦截器链按排序后的顺序依次执行,每个拦截器根据其类型决定是否继续执行后续逻辑:
(1)@Around
通知
- 执行前:记录方法开始时间、参数等信息。
- 控制是否继续:通过调用
proceed()
方法决定是否执行后续拦截器或目标方法。若不调用proceed()
,目标方法不会执行。
(2)@Before
通知
- 直接执行前置逻辑(如日志记录),然后自动调用后续拦截器或目标方法(无需显式调用
proceed()
)。
(3)目标方法执行
若所有前置拦截器(@Before
、@Around
中调用 proceed()
)执行完毕,目标方法被调用。
(4)@AfterReturning
通知
- 目标方法成功返回后执行(可获取返回值)。
(5)@AfterThrowing
通知
- 目标方法抛出异常后执行(可获取异常对象)。
(6)@After
通知
- 目标方法执行完成后(无论成功或异常)执行。
4. 返回结果
最终结果(目标方法返回值或异常)通过拦截器链传递回客户端。
四、Mermaid 流程图:拦截器链的构建与执行
1. 拦截器链构建流程图
graph TD
A[Spring 容器初始化] --> B[扫描 @Aspect 切面]
B --> C[提取 @Pointcut、@Before、@After 等注解]
C --> D[生成 Advisor(切点+通知)]
D --> E[按 @Order 排序 Advisor]
E --> F[ProxyFactory 生成代理对象]
F --> G[代理对象持有拦截器链]
2. 拦截器链执行流程图
graph TD
A["客户端调用代理方法"] --> B["触发 InvocationHandler"]
B --> C["执行拦截器链"]
C --> D{"@Around 通知: 调用 proceed()?"}
D -- 是 --> E["@Before 通知"]
D -- 否 --> Z[结束链,不执行目标方法]
E --> F["@AfterReturning 通知(目标方法成功"]
F --> G["@After 通知"]
E --> H["目标方法执行"]
H --> I{"@AfterThrowing 通知(目标方法异常)"}
I --> G
G --> Z
五、关键源码与调试技巧
1. 查看拦截器链
通过调试 AdvisedSupport
类的 advisors
字段,可查看当前代理对象的所有拦截器:
// 在 ProxyFactory 中获取 AdvisedSupport
AdvisedSupport advised = (AdvisedSupport) ((Advised) proxy).getAdvisors();
for (Advisor advisor : advised.getAdvisors()) {
System.out.println("Advisor: " + advisor);
}
2. 动态修改拦截器链
Spring 允许通过 AopConfig
动态添加/移除 Advisor(需手动触发代理更新):
// 获取代理对象的 Advised 支持
Advised advised = (Advised) targetObject;
// 添加新的 Advisor
advised.addAdvisor(new MyAdvisor());
// 重新生成代理(可选)
六、总结
拦截器链是 Spring AOP 实现横切逻辑的核心机制,其构建流程涉及切面扫描、Advisor 生成、排序、代理生成,执行流程则通过动态代理触发拦截器的链式调用。理解这一过程有助于:
- 调试 AOP 逻辑(如查看拦截器顺序)。
- 自定义拦截器(如实现
MethodInterceptor
)。 - 优化性能(如减少不必要的拦截器)。
通过结合源码和 Mermaid 流程图, 我们可更直观地掌握 AOP 拦截器链的工作原理,从而在实际项目中灵活应用。