有一種答案是指定order,order越小越先執行。這種答案不算錯,可是有些片面。java
更改Aspect的Order有三中方式,1:經過實現org.springframework.core.Ordered接口;2:經過註解@Order(1) ;3:經過配置文件配置 spring
咱們實驗採用註解的方式,定義兩個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就是面向切面編程,什麼是切面,畫一個圖來理解下:
由此得出:api
應用舉例:測試
若是咱們要在同一個方法事務提交後執行本身的AOP,那麼把事務的AOP order設置爲2,本身的AOP order設置爲1,而後在doAfterReturn裏邊處理本身的業務邏輯this