多个切面执行顺序
多个切面作用于同一连接点时,执行顺序通过优先级控制。
执行顺序规则
切面执行遵循洋葱模型:
- 高优先级切面:先执行前置,后执行后置
- 低优先级切面:后执行前置,先执行后置
Java
┌─────────────────────────┐
│ Aspect1 @Before │ ← 高优先级(小数值)
├─────────────────────────┤
│ Aspect2 @Before │
├─────────────────────────┤
│ Target Method │
├─────────────────────────┤
│ Aspect2 @After/AfterReturning
├─────────────────────────┤
│ Aspect1 @After/AfterReturning
└─────────────────────────┘
@Order注解方式
Java
@Aspect
@Component
@Order(1) // 数值越小优先级越高
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeLog() {
System.out.println("LogAspect - 前置日志");
}
@After("execution(* com.example.service.*.*(..))")
public void afterLog() {
System.out.println("LogAspect - 后置日志");
}
}
@Aspect
@Component
@Order(2) // 优先级低于LogAspect
public class TxAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeTx() {
System.out.println("TxAspect - 开启事务");
}
@After("execution(* com.example.service.*.*(..))")
public void afterTx() {
System.out.println("TxAspect - 提交事务");
}
}
Ordered接口方式
Java
@Aspect
@Component
public class SecurityAspect implements Ordered {
@Override
public int getOrder() {
return 0; // 最高优先级
}
@Before("execution(* com.example.service.*.*(..))")
public void checkSecurity() {
System.out.println("SecurityAspect - 安全检查");
}
}
@Priority注解方式
Java
@Aspect
@Component
@Priority(1)
public class ValidationAspect {
@Before("execution(* com.example.service.*.*(..))")
public void validate() {
System.out.println("ValidationAspect - 参数校验");
}
}
三种方式优先级对比
| 方式 | 说明 | 推荐度 |
|---|---|---|
| @Order | 简洁直观,可配置任意值 | ★★★★★ |
| Ordered接口 | 灵活,可动态计算优先级 | ★★★★ |
| @Priority | JSR-250标准,Spring支持 | ★★★ |
实际开发中推荐使用@Order注解,简洁明了。
完整执行示例
text
// 执行顺序:SecurityAspect(0) → LogAspect(1) → TxAspect(2)
// 输出结果:
// SecurityAspect - 安全检查
// LogAspect - 前置日志
// TxAspect - 开启事务
// [目标方法执行]
// TxAspect - 提交事务
// LogAspect - 后置日志
// SecurityAspect - 后置处理
要点总结
- Order数值越小,优先级越高
- 前置通知按优先级顺序执行
- 后置通知按优先级逆序执行
- @Order注解是最常用方式
- 未指定Order时执行顺序不确定
📝 发现内容有误?点击此处直接编辑