有一种答案是指定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就是面向切面编程,什么是切面,画一个图来理解下:
如果我们要在同一个方法事务提交后执行自己的AOP,那么把事务的AOP order设置为2,自己的AOP order设置为1,然后在doAfterReturn里边处理自己的业务逻辑