前置通知环绕通知后置通知执行的先后顺序

在 Spring AOP 中,当**前置通知(@Before)、环绕通知(@Around)、后置通知(@AfterReturning)**同时作用于同一个方法时,它们的执行顺序遵循明确的规则。以下是完整的执行流程和优先级说明:


1. 标准执行顺序

当所有通知同时存在时,完整的执行链条如下:

1. 环绕通知(@Around)的前半部分
   → 2. 前置通知(@Before)
      → 3. 目标方法执行
   → 4. 环绕通知(@Around)的后半部分
→ 5. 后置通知(@AfterReturning
图示流程
@Around @Before 目标方法 @AfterReturning proceed()调用前 方法执行完成 proceed()调用后 @Around @Before 目标方法 @AfterReturning

2. 关键细节说明

(1) 环绕通知(@Around)是主导者
  • 只有调用 ProceedingJoinPoint.proceed() 时,才会触发后续通知和目标方法。
  • 如果环绕通知中不调用 proceed(),则整个链条终止(目标方法和其他通知都不会执行)。
(2) 异常情况下的行为
  • 如果目标方法或通知抛出异常:
    • 后置通知(@AfterReturning)不会执行
    • 环绕通知的后续代码也不会执行
    • @After(最终通知)仍会执行(如果有)
(3) 多个同类型通知的执行顺序

如果存在多个同类型通知(如多个 @Around),其顺序由 @Order 注解Ordered 接口控制,数值越小优先级越高。


3. 代码示例验证

定义切面
@Aspect
@Component
public class MyAspect {
    
    

    @Before("execution(* com.example.service.*.*(..))")
    public void beforeAdvice() {
    
    
        System.out.println("[前置通知] @Before");
    }

    @Around("execution(* com.example.service.*.*(..))")
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
    
    
        System.out.println("[环绕通知] @Around - 前");
        Object result = pjp.proceed(); // 触发目标方法和其他通知
        System.out.println("[环绕通知] @Around - 后");
        return result;
    }

    @AfterReturning("execution(* com.example.service.*.*(..))")
    public void afterReturningAdvice() {
    
    
        System.out.println("[后置通知] @AfterReturning");
    }
}
执行输出

当目标方法被调用时,控制台输出:

[环绕通知] @Around - 前
[前置通知] @Before
[目标方法执行]
[环绕通知] @Around - 后
[后置通知] @AfterReturning

4. 与其他通知的完整顺序

如果加入 最终通知(@After)异常通知(@AfterThrowing),完整顺序为:

  1. @Around 前半
  2. @Before
  3. 目标方法
    • 成功:
      4. @AfterReturning
      5. @Around 后半
      6. @After(最终通知)
    • 失败(抛出异常):
      4. @AfterThrowing
      5. @After(最终通知)

5. 设计建议

  • 控制流:通过环绕通知可以完全控制目标方法是否执行。
  • 性能敏感:避免在环绕通知中添加耗时逻辑,因其在调用链的最外层。
  • 事务管理:Spring 的事务通知(@Transactional)本质是环绕通知,优先级通常最高。

理解这一执行顺序对调试复杂 AOP 场景至关重要,尤其是在需要多个通知协同工作时。