Spring-Order註解

若是咱們在同一個方法自定義多個AOP,如何執行執行順序?

有一種答案是指定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

  1. spring aop就是一個同心圓,要執行的方法爲圓心,最外層的order最小
  2. 從最外層按照LogAspect、SignAspect的順序依次執行doAround方法,doBefore方法
  3. 而後執行method方法
  4. 最後按照SignAspect、LogAspect的順序依次執行doAfter、doAfterReturn方法
  5. 也就是說對多個AOP來講,先before的,必定後after

應用舉例:測試

若是咱們要在同一個方法事務提交後執行本身的AOP,那麼把事務的AOP order設置爲2,本身的AOP order設置爲1,而後在doAfterReturn裏邊處理本身的業務邏輯this

相關文章
相關標籤/搜索