Spring Boot [AOP](三) 通知执行链源码解析
1. 执行链概述
在 Spring AOP 中,一个方法可能对应 多个切面(Aspect) 和 多个通知(Advice) 。Spring 使用 Advisor 链 + MethodInterceptor 链 来统一管理这些通知,使方法执行时按顺序执行各类通知。
核心概念
| 概念 | 说明 |
|---|---|
| Advisor | 切面 + 切入点 + 通知的组合对象 |
| Advice | 切面中具体执行的操作,例如 @Before、@After、@Around |
| MethodInterceptor | AOP 的统一调用接口,所有 Advice 最终都转换为 MethodInterceptor |
| ReflectiveMethodInvocation | 方法调用封装类,负责顺序调用 Advisor 链 |
Spring AOP 的通知最终都会被封装为 MethodInterceptor,执行链由 ReflectiveMethodInvocation 管理。
2. Advisor 链与通知统一处理
在 Spring 中,多个[切面]可能作用于同一个方法。Spring 会将所有切面对应的通知 排序后加入 Advisor 链:
- 收集匹配的切面
- 将切面中的 Advice 转换为 MethodInterceptor
- 按 @Order 或实现 Ordered 接口排序
- 构建 ReflectiveMethodInvocation 执行链
Mermaid 流程图:Advisor 链构建
扫描 Bean 切面
匹配切入点
收集匹配的通知
Advice 转换为 MethodInterceptor
按顺序构建 ReflectiveMethodInvocation 链
3. MethodInterceptor 执行流程
3.1 ReflectiveMethodInvocation 核心源码
核心方法:proceed()
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.method.invoke(this.target, this.arguments);
}
Object interceptorOrAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrAdvice instanceof MethodInterceptor) {
return ((MethodInterceptor) interceptorOrAdvice).invoke(this);
} else {
return proceed();
}
}
AI写代码java
运行
123456789101112
3.2 执行逻辑说明
currentInterceptorIndex控制当前执行的通知- 如果到达链尾,则调用目标方法
- 否则,将当前通知强转为 MethodInterceptor 并调用
- 每个环绕通知内部可以调用
proceed()执行下一环节
Mermaid 流程图:MethodInterceptor 调用链
AI写代码mermaid
123456789101112131415161718
4. 不同通知类型执行链示意
| 通知类型 | 转换为 MethodInterceptor | 执行顺序 |
|---|---|---|
| 前置通知 @Before | MethodBeforeAdviceInterceptor | 最先执行 |
| 环绕通知 @Around | AroundAdviceInterceptor | 可环绕目标方法 |
| 返回通知 @AfterReturning | AfterReturningAdviceInterceptor | 目标方法成功返回后执行 |
| 异常通知 @AfterThrowing | AfterThrowingAdviceInterceptor | 目标方法异常时执行 |
| 后置通知 @After | AfterAdviceInterceptor | 最后执行,无论成功/异常 |
5. 环绕通知执行链深入解析
环绕通知最灵活,可以完全控制方法执行:
@Around("execution(* com.example.service..*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知前逻辑");
Object result = pjp.proceed();
System.out.println("环绕通知后逻辑");
return result;
}
AI写代码java
运行
1234567
Mermaid 流程图:环绕通知链执行
方法调用
环绕通知1前逻辑
环绕通知2前逻辑
目标方法执行
环绕通知2后逻辑
环绕通知1后逻辑
返回调用方
6. 多 Advisor 链组合示例
@Aspect
@Component
@Order(1)
public class LoggingAspect {
@Before("execution(* com.example.service..*.*(..))")
public void before(JoinPoint jp) {
System.out.println("日志前置: " + jp.getSignature());
}
}
@Aspect
@Component
@Order(2)
public class TransactionAspect {
@Around("execution(* com.example.service..*.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("事务开始");
Object result = pjp.proceed();
System.out.println("事务提交");
return result;
}
}
@Aspect
@Component
@Order(3)
public class MetricsAspect {
@AfterReturning(pointcut = "execution(* com.example.service..*.*(..))", returning = "result")
public void afterReturning(JoinPoint jp, Object result) {
System.out.println("性能监控: " + jp.getSignature() + ", 返回: " + result);
}
}
AI写代码java
运行
1234567891011121314151617181920212223242526272829303132
多切面执行顺序示意
AI写代码mermaid
1234567
7. ReflectiveMethodInvocation 执行链源码示意
是
否
proceed 方法调用
获取当前索引的 MethodInterceptor
索引是否到达链尾?
执行目标方法 method.invoke
执行当前拦截器
interceptor.invoke this
拦截器内部调用 proceed
返回结果
逐层返回到调用方
8. 本文总结
- Spring AOP 统一将所有通知封装为 MethodInterceptor
ReflectiveMethodInvocation负责 链式执行所有通知- 环绕通知可以完全控制目标方法执行,其他通知按 Advisor 链顺序执行
- 多切面组合执行顺序由
@Order或Ordered接口控制 - Mermaid 图直观展示了 Advisor 链、方法调用链和环绕通知执行顺序