多个AOP切面注解 执行顺序说明
所属分类 spring
浏览量 23
在 Spring AOP 中,同一个方法上多个 AOP 注解的执行顺序取决于注解类型、切面类的定义以及是否显式指定优先级
1. 同一类型注解的执行顺序
场景:多个相同类型的 AOP 注解(如多个 @Before)
默认顺序:按切面类的 声明顺序 执行(Spring 默认按字母顺序排序类名)
显式控制顺序:使用 @Order 注解指定优先级(值越小越先执行)
@Aspect
@Order(1)
@Component
public class Aspect1 {
@Before("execution(* com.example.MyService.myMethod(..))")
public void before1() {
System.out.println("Aspect1 Before");
}
}
@Aspect
@Order(2)
@Component
public class Aspect2 {
@Before("execution(* com.example.MyService.myMethod(..))")
public void before2() {
System.out.println("Aspect2 Before");
}
}
输出顺序:
Aspect1 Before
Aspect2 Before
2. 不同类型注解的执行顺序
常见注解类型及其执行顺序:
@Around:环绕通知,最先执行,包裹整个方法调用
@Before:在目标方法执行前执行
目标方法:实际业务逻辑
@After:目标方法执行后执行(无论是否异常)
@AfterReturning:目标方法成功返回后执行
@AfterThrowing:目标方法抛出异常后执行
示例:
@Aspect
@Component
public class MyAspect {
@Around("execution(* com.example.MyService.myMethod(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Around Before");
Object result = joinPoint.proceed();
System.out.println("Around After");
return result;
}
@Before("execution(* com.example.MyService.myMethod(..))")
public void before() {
System.out.println("Before");
}
@After("execution(* com.example.MyService.myMethod(..))")
public void after() {
System.out.println("After");
}
}
执行顺序:
Around Before
Before
目标方法
After
Around After
3. 多个切面类的执行顺序
场景:多个切面类对同一方法定义了相同类型的注解
默认顺序:按 Spring Bean 的 加载顺序 执行(通常按类名字母顺序)
显式控制顺序:在切面类上使用 @Order 注解
示例:
@Aspect
@Order(1)
@Component
public class Aspect1 {
@Before("execution(* com.example.MyService.myMethod(..))")
public void before1() {
System.out.println("Aspect1 Before");
}
}
@Aspect
@Order(2)
@Component
public class Aspect2 {
@Before("execution(* com.example.MyService.myMethod(..))")
public void before2() {
System.out.println("Aspect2 Before");
}
}
输出顺序:
Aspect1 Before
Aspect2 Before
4. 特殊情况:@Around 与其他注解的交互
@Around 的优先级:@Around 会包裹整个方法调用流程,因此它的执行顺序会影响其他注解的触发时机
示例:如果 @Around 决定不调用 joinPoint.proceed(),则后续的 @Before、目标方法等都不会执行
@Aspect
@Component
public class AroundAspect {
@Around("execution(* com.example.MyService.myMethod(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Around Before");
// 如果注释掉下一行,目标方法及后续注解都不会执行
Object result = joinPoint.proceed();
System.out.println("Around After");
return result;
}
}
5. 总结:执行顺序规则
注解类型 执行阶段 说明
@Around 最先执行,包裹整个流程 控制是否调用 proceed()
@Before 在目标方法执行前 所有 @Before 按 @Order 或声明顺序执行
目标方法 实际业务逻辑
@After 目标方法执行后(无论是否异常)
@AfterReturning 目标方法成功返回后
@AfterThrowing 目标方法抛出异常后
6. 实际应用建议
显式指定顺序:对关键切面(如权限校验、日志记录)使用 @Order 避免依赖默认排序
避免过度依赖顺序:尽量将职责单一的切面解耦,减少顺序依赖
测试验证:通过单元测试或日志输出确认实际执行顺序
通过合理使用 @Order 和理解注解类型的作用阶段,可以灵活控制 AOP 的执行顺序,确保切面逻辑按预期工作
上一篇
spring事务的一些知识点
MyBatis Plus 动态数据源注解 @DS 注解
MyBatis Plus @DS注解原理