如果我们在同一个方法自定义多个AOP,如何执行执行顺序?
有一种答案是指定order,order越小越先执行。这种答案不算错,但是有些片面。
更改Aspect的Order有三中方式,1:通过实现org.springframework.core.Ordered接口;2:通过注解@Order(1) ;3:通过配置文件配置
我们实验采用注解的方式,定义两个Aspect:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
String description() default "";
}
order=1001
代码块
java
@Aspect
@Component
@Order(1001)
public class LogAspect {
private final Logger logger \= LoggerFactory.getLogger(this.getClass());
//日志注解
@Pointcut(value \= "@annotation(com.meituan.pay.mapi.aspect.Log)")
public void logAspect() {
}
//声明前置通知
@Before("logAspect()")
public void doBefore(JoinPoint point) {
logger.info("logAspect:doBefore");
return;
}
//声明后置通知
@AfterReturning(pointcut \= "logAspect()", returning \= "returnValue")
public void doAfterReturning(JoinPoint point, Object returnValue) {
logger.info("logAspect:doAfterReturning");
}
//声明例外通知
@AfterThrowing(pointcut \= "logAspect()", throwing \= "e")
public void doAfterThrowing(Exception e) {
logger.info("logAspect:doAfterThrowing");
}
//声明最终通知
@After("logAspect()")
public void doAfter() {
logger.info("logAspect:doAfter");
}
//声明环绕通知
@Around("logAspect()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
logger.info("logAspect:doAround-start");
Object obj \= pjp.proceed();
logger.info("logAspect:doAround-end");
return obj;
}
}
**SignAspect:**
代码块
java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Sign {
String description() default "";
}
order=1002
代码块
java
@Aspect
@Component
@Order(1002)
public class SignAspect {
private final Logger logger \= LoggerFactory.getLogger(this.getClass());
//日志注解
@Pointcut(value \= "@annotation(com.meituan.pay.mapi.aspect.Sign)")
public void signAspect() {
}
//声明前置通知
@Before("signAspect()")
public void doBefore(JoinPoint point) {
logger.info("signAspect:doBefore");
return;
}
//声明后置通知
@AfterReturning(pointcut \= "signAspect()", returning \= "returnValue")
public void doAfterReturning(JoinPoint point, Object returnValue) {
logger.info("signAspect:doAfterReturning");
}
//声明例外通知
@AfterThrowing(pointcut \= "signAspect()", throwing \= "e")
public void doAfterThrowing(Exception e) {
logger.info("signAspect:doAfterThrowing");
}
//声明最终通知
@After("signAspect()")
public void doAfter() {
logger.info("signAspect:doAfter");
}
//声明环绕通知
@Around("signAspect()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
logger.info("signAspect:doAround-start");
Object obj \= pjp.proceed();
logger.info("signAspect:doAround-end");
return obj;
}
}
**测试:**
代码块
java
@Service
public class AspectTestService {
private static final Logger LOGGER \= LoggerFactory.getLogger(AspectTestService.class);
@Sign
@Log
public void testAspect() {
LOGGER.info("执行方法");
}
}
**最终输出:**
代码块
java
LogAspect (LogAspect.java:55) logAspect:doAround\-start
LogAspect (LogAspect.java:30) logAspect:doBefore
SignAspect (SignAspect.java:54) signAspect:doAround\-start
SignAspect (SignAspect.java:29) signAspect:doBefore
AspectTestService (AspectTestService.java:19) 执行方法
SignAspect (SignAspect.java:56) signAspect:doAround\-end
SignAspect (SignAspect.java:48) signAspect:doAfter
SignAspect (SignAspect.java:36) signAspect:doAfterReturning
LogAspect (LogAspect.java:57) logAspect:doAround\-end
LogAspect (LogAspect.java:49) logAspect:doAfter
LogAspect (LogAspect.java:37) logAspect:doAfterReturning
**结论:**
从上面的测试我们看到,确实是order越小越是最先执行,但更重要的是最先执行的最后结束。
AOP就是面向切面编程,什么是切面,画一个图来理解下:
由此得出:
- spring aop就是一个同心圆,要执行的方法为圆心,最外层的order最小
- 从最外层按照LogAspect、SignAspect的顺序依次执行doAround方法,doBefore方法
- 然后执行method方法
- 最后按照SignAspect、LogAspect的顺序依次执行doAfter、doAfterReturn方法
- 也就是说对多个AOP来说,先before的,一定后after
应用举例:
如果我们要在同一个方法事务提交后执行自己的AOP,那么把事务的AOP order设置为2,自己的AOP order设置为1,然后在doAfterReturn里边处理自己的业务逻辑
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。