你的理解部分正确,但需要更精准的修正。Spring AOP 的拦截器链顺序和实际执行顺序之间存在递归推进关系,这需要结合拦截器的具体实现来理解。我们以你的代码为例详细分析:
1. 拦截器链的构造顺序
在你的代码中,@Before 和 @After 两个通知会被转换为以下拦截器,并按如下顺序加入链中:
- 
MethodBeforeAdviceInterceptor(对应@Before)
- 
AspectJAfterAdvice(对应@After)
拦截器链的顺序是:@Before → @After(注意:此时原始方法尚未执行!)。
2. 拦截器链的执行顺序(关键)
当 ReflectiveMethodInvocation.proceed() 被调用时,拦截器链的执行流程如下:
(1) 初始状态
- currentInterceptorIndex = -1
- 拦截器链顺序:[MethodBeforeAdviceInterceptor, AspectJAfterAdvice]
  
  
  (2) 第一次调用 proceed()
- 
currentInterceptorIndex递增为0(第一个拦截器:MethodBeforeAdviceInterceptor)
- 执行 MethodBeforeAdviceInterceptor.invoke(this):
  // 伪代码:MethodBeforeAdviceInterceptor 的逻辑
  public Object invoke(MethodInvocation mi) {
      // 1. 先执行前置通知(@Before)
      this.advice.before(...);
      // 2. 继续调用 mi.proceed() → 触发下一个拦截器
      return mi.proceed();
  }
- 此时会打印 "AOP 前置通知",然后继续调用 mi.proceed()。
  
  
  (3) 第二次调用 proceed()
- 
currentInterceptorIndex递增为1(第二个拦截器:AspectJAfterAdvice)
- 执行 AspectJAfterAdvice.invoke(this):
  // 伪代码:AspectJAfterAdvice 的逻辑
  public Object invoke(MethodInvocation mi) {
      try {
          // 1. 继续调用 mi.proceed() → 此时已无后续拦截器,触发原始方法调用
          Object result = mi.proceed();
          return result;
      } finally {
          // 2. 无论是否异常,执行后置通知(@After)
          invokeAdviceMethod(...);
      }
  }
- 调用 mi.proceed()时,currentInterceptorIndex已达到链的末尾(1 == 1),因此执行原始方法invokeJoinpoint()→ 打印 "执行业务逻辑"。
- 
最后,在 finally块中打印 "AOP 后置通知"。
3. 执行顺序总结
虽然拦截器链的顺序是 @Before → @After,但实际执行顺序是:
@Before → 原始方法 → @After
这是因为 @After 对应的拦截器(AspectJAfterAdvice)在它的 invoke() 方法中,先调用 mi.proceed() 触发后续逻辑(包括原始方法),然后在 finally 块中执行后置通知。
关键设计思想
- 
递归式链式调用:每个拦截器在完成自身逻辑后,必须显式调用 mi.proceed()才能推进链的执行。
- 
后置通知的 finally 保证:@After的逻辑包裹在finally块中,确保无论方法是否抛出异常都会执行。
- 拦截器顺序 ≠ 执行顺序:拦截器的排列顺序决定了它们拦截的优先级,但具体执行顺序由每个拦截器的内部逻辑决定。
验证方法
- 
调试 ReflectiveMethodInvocation:- 在 proceed()方法中观察currentInterceptorIndex的变化。
- 在 MethodBeforeAdviceInterceptor.invoke()和AspectJAfterAdvice.invoke()中设置断点,观察调用顺序。
 
- 在 
- 
查看拦截器链内容: - 在 CglibAopProxy.DynamicAdvisedInterceptor.intercept()方法中,检查拦截器链的组成:
 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
- 在 
- 
观察 AspectJAfterAdvice的invoke()方法:- 注意 mi.proceed()的调用触发原始方法,而@After逻辑在finally块中执行。
 
- 注意 
总结流程图
1. 代理方法调用
   │
   └─ ReflectiveMethodInvocation.proceed()
        │
        ├─ 执行 MethodBeforeAdviceInterceptor(@Before)
        │    │
        │    └─ 调用 proceed() → 推进到下一个拦截器
        │
        ├─ 执行 AspectJAfterAdvice(@After)
        │    │
        │    ├─ 调用 proceed() → 触发原始方法
        │    │    │
        │    │    └─ 执行原始方法(TargetService.doSomething())
        │    │
        │    └─ finally 块执行 @After 逻辑
        │
        └─ 返回结果
通过这种设计,Spring AOP 实现了 @Before → 原始方法 → @After 的执行顺序,而拦截器链的物理顺序只是实现这一逻辑的手段。
 

 
    
Top comments (0)