Spring Boot AOP(三) 通知执行链源码解析

8 阅读3分钟

Spring Boot [AOP](三) 通知执行链源码解析

1. 执行链概述

在 Spring AOP 中,一个方法可能对应 多个切面(Aspect)  和 多个通知(Advice) 。Spring 使用 Advisor 链 + MethodInterceptor 链 来统一管理这些通知,使方法执行时按顺序执行各类通知。

核心概念

概念说明
Advisor切面 + 切入点 + 通知的组合对象
Advice切面中具体执行的操作,例如 @Before、@After、@Around
MethodInterceptorAOP 的统一调用接口,所有 Advice 最终都转换为 MethodInterceptor
ReflectiveMethodInvocation方法调用封装类,负责顺序调用 Advisor 链

Spring AOP 的通知最终都会被封装为 MethodInterceptor,执行链由 ReflectiveMethodInvocation 管理。


2. Advisor 链与通知统一处理

在 Spring 中,多个[切面]可能作用于同一个方法。Spring 会将所有切面对应的通知 排序后加入 Advisor 链

  1. 收集匹配的切面
  2. 将切面中的 Advice 转换为 MethodInterceptor
  3. 按 @Order 或实现 Ordered 接口排序
  4. 构建 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 执行逻辑说明

  1. currentInterceptorIndex 控制当前执行的通知
  2. 如果到达链尾,则调用目标方法
  3. 否则,将当前通知强转为 MethodInterceptor 并调用
  4. 每个环绕通知内部可以调用 proceed() 执行下一环节

Mermaid 流程图:MethodInterceptor 调用链

AI写代码mermaid
123456789101112131415161718

4. 不同通知类型执行链示意

通知类型转换为 MethodInterceptor执行顺序
前置通知 @BeforeMethodBeforeAdviceInterceptor最先执行
环绕通知 @AroundAroundAdviceInterceptor可环绕目标方法
返回通知 @AfterReturningAfterReturningAdviceInterceptor目标方法成功返回后执行
异常通知 @AfterThrowingAfterThrowingAdviceInterceptor目标方法异常时执行
后置通知 @AfterAfterAdviceInterceptor最后执行,无论成功/异常

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 链、方法调用链和环绕通知执行顺序