在 Spring Boot 应用开发中,切面编程(AOP)是一项强大的功能,它允许我们将横切关注点(如日志记录、事务管理、权限控制等)从业务逻辑中分离出来,以提高代码的可维护性和可扩展性。当存在多个切面时,了解和控制切面的执行优先级顺序就显得尤为重要。本文将深入介绍 Spring Boot 框架中切面执行优先级顺序的使用方式。
在 Spring AOP 中,切面的优先级决定了多个切面在目标方法执行前后的执行顺序。高优先级的切面会先于低优先级的切面执行。在环绕通知(@Around)中,高优先级切面的通知方法先进入,后退出;而在前置通知(@Before)中,高优先级切面的通知方法先执行,后置通知(@After)和返回后通知(@AfterReturning)以及异常通知(@AfterThrowing)则相反,低优先级切面的通知方法先执行。
@Order
,数值越小优先级越高。@Aspect
@Component
@Order(1) // 优先级高于 Order(2) 的切面
public class LogAspect {
// 切面逻辑
}
@Order
的切面默认优先级最低(数值最大)。Ordered
接口@Aspect
@Component
public class ValidationAspect implements Ordered {
@Override
public int getOrder() {
return 2; // 优先级低于返回 1 的切面
}
}
假设切面 OrderDemoAspect1(优先级1), OrderDemoAspect2(优先级2),OrderDemoAspect3(优先级2)和 OrderDemoAspect4(默认优先级)作用于同一方法:
@Around 开始
→@Before
→@Before
→@Aspect
@Component
@Order(1)
public class OrderDemoAspect1 {
@Before("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public void before() {
System.out.println("OrderDemoAspect1 before");
}
@After("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public void after() {
System.out.println("OrderDemoAspect1 after");
}
@AfterReturning(pointcut = "@annotation(com.shore.annotation.OrderDemoAnnotation)", returning = "result")
public void afterReturning(Object result) {
System.out.println("OrderDemoAspect1 afterReturning with result: " + result);
}
@AfterThrowing(pointcut = "@annotation(com.shore.annotation.OrderDemoAnnotation)", throwing = "exception")
public void afterThrowing(Throwable exception) {
System.out.println("OrderDemoAspect1 afterThrowing exception: " + exception);
}
@Around("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("OrderDemoAspect1 around Before execution of a method (Around advice)");
// 继续执行原方法
Object result = joinPoint.proceed(joinPoint.getArgs());
System.out.println("OrderDemoAspect1 around After execution of a method (Around advice)");
return result;
}
}
@Aspect
@Component
@Order(2)
public class OrderDemoAspect2 {
@Before("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public void before() {
System.out.println("OrderDemoAspect2 before");
}
@After("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public void after() {
System.out.println("OrderDemoAspect2 after");
}
@AfterReturning(pointcut = "@annotation(com.shore.annotation.OrderDemoAnnotation)", returning = "result")
public void afterReturning(Object result) {
System.out.println("OrderDemoAspect2 afterReturning with result: " + result);
}
@AfterThrowing(pointcut = "@annotation(com.shore.annotation.OrderDemoAnnotation)", throwing = "exception")
public void afterThrowing(Throwable exception) {
System.out.println("OrderDemoAspect2 afterThrowing exception: " + exception);
}
@Around("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("OrderDemoAspect2 around Before execution of a method (Around advice)");
// 继续执行原方法
Object result = joinPoint.proceed(joinPoint.getArgs());
System.out.println("OrderDemoAspect2 around After execution of a method (Around advice)");
return result;
}
}
@Aspect
@Component
@Order(2)
public class OrderDemoAspect3 {
@Before("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public void before() {
System.out.println("OrderDemoAspect3 before");
}
@After("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public void after() {
System.out.println("OrderDemoAspect3 after");
}
@AfterReturning(pointcut = "@annotation(com.shore.annotation.OrderDemoAnnotation)", returning = "result")
public void afterReturning(Object result) {
System.out.println("OrderDemoAspect3 afterReturning with result: " + result);
}
@AfterThrowing(pointcut = "@annotation(com.shore.annotation.OrderDemoAnnotation)", throwing = "exception")
public void afterThrowing(Throwable exception) {
System.out.println("OrderDemoAspect3 afterThrowing exception: " + exception);
}
@Around("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("OrderDemoAspect3 around Before execution of a method (Around advice)");
// 继续执行原方法
Object result = joinPoint.proceed(joinPoint.getArgs());
System.out.println("OrderDemoAspect3 around After execution of a method (Around advice)");
return result;
}
}
@Aspect
@Component
public class OrderDemoAspect4 {
@Before("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public void before() {
System.out.println("OrderDemoAspect4 before");
}
@After("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public void after() {
System.out.println("OrderDemoAspect4 after");
}
@AfterReturning(pointcut = "@annotation(com.shore.annotation.OrderDemoAnnotation)", returning = "result")
public void afterReturning(Object result) {
System.out.println("OrderDemoAspect4 afterReturning with result: " + result);
}
@AfterThrowing(pointcut = "@annotation(com.shore.annotation.OrderDemoAnnotation)", throwing = "exception")
public void afterThrowing(Throwable exception) {
System.out.println("OrderDemoAspect4 afterThrowing exception: " + exception);
}
@Around("@annotation(com.shore.annotation.OrderDemoAnnotation)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("OrderDemoAspect4 around Before execution of a method (Around advice)");
// 继续执行原方法
Object result = joinPoint.proceed(joinPoint.getArgs());
System.out.println("OrderDemoAspect4 around After execution of a method (Around advice)");
return result;
}
}
OrderDemoAspect1 around Before execution of a method (Around advice)
OrderDemoAspect1 before
OrderDemoAspect2 around Before execution of a method (Around advice)
OrderDemoAspect2 before
OrderDemoAspect3 around Before execution of a method (Around advice)
OrderDemoAspect3 before
OrderDemoAspect4 around Before execution of a method (Around advice)
OrderDemoAspect4 before
OrderDemoAspect4 afterReturning with result: Order Demo
OrderDemoAspect4 after
OrderDemoAspect4 around After execution of a method (Around advice)
OrderDemoAspect3 afterReturning with result: Order Demo
OrderDemoAspect3 after
OrderDemoAspect3 around After execution of a method (Around advice)
OrderDemoAspect2 afterReturning with result: Order Demo
OrderDemoAspect2 after
OrderDemoAspect2 around After execution of a method (Around advice)
OrderDemoAspect1 afterReturning with result: Order Demo
OrderDemoAspect1 after
OrderDemoAspect1 around After execution of a method (Around advice)
@Before
)默认按方法名字典序执行,@Order
无法直接调整同类通知顺序。@Order
注解,避免因实现 Ordered
接口引入额外复杂度。