1. 程式人生 > 實用技巧 >3.25 切面釋出-通知順序-@Order

3.25 切面釋出-通知順序-@Order

戴著假髮的程式設計師出品 抖音ID:戴著假髮的程式設計師歡迎關注

[檢視視訊教程]

有時我們可能在我們的業務上會增加多個相同型別的切面。這時就會有一個先後順序問題。那麼spring如何解決順序問題呢?

在使用註解方式的環境下,我們可以通過@Order註解給切面排序,當然在沒有@Order註解的情況下,多個切面本身是無順序的(也就是按照預設順序執行)。

這裡要注意一個問題,@Order註解只有在@Aspect類上才生效,也就是下面的註解方式才生效:

1 @Component
2 @Aspect
3 @Order(1)
4 public class DkAspect1 {}
1 @Component
2 @Aspect 3 @Order(2) 4 public class DkAspect2 {}

所以如果我們有多個攔截需要排序,就需要將這個切面配置在不同的Aspect類中。

在同一個Aspect類中Advice方法是無法排序的,

我們看案例:

我們在一個Aspect類中準備三個前置通知,切入同一個切入點

 1 /**
 2  * @author 戴著假髮的程式設計師
 3  * 
 4  * @description
 5  */
 6 @Component
 7 @Aspect
 8 public class DkAspect {
 9     @Pointcut("execution(* com.st.dk.demo8.service..*.*(..))")
10 public void pointcut1(){} 11 12 @Before("pointcut1()") 13 public void beforeB(){ 14 System.out.println("--前置通知--BBB--"); 15 } 16 @Before("pointcut1()") 17 public void beforeA(){ 18 System.out.println("--前置通知--AAA--"); 19 } 20 21 @Before("pointcut1()")
22 public void beforeC(){ 23 System.out.println("--前置通知--CCC--"); 24 } 25 }

我們來看看自然順序:

很明顯所謂自然順序就是按照方法的名稱的數字或者字母順序排序的,並非方法的編寫順序。

我們來看看Order註解的原始碼:

1 package org.springframework.core.annotation;
2 
3 @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
4 @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD})
5 @java.lang.annotation.Documented
6 public @interface Order {
7     int value() default 2147483647;
8 }

我們會發現Order中的value預設值是整形的最大值,而spring在對通知排序時,order中的value越小,優先順序越高。

現在我們來使用Order註解控制我們的通知順序:

 1 /**
 2  * @author 戴著假髮的程式設計師
 3  * 
 4  * @description
 5  */
 6 @Component
 7 @Aspect
 8 @Order(1)//第一順位
 9 public class DKAspect1 {
10     @Pointcut("execution(* com.st.dk.demo8.service..*.*(..))")
11     public void pointcut1(){}
12 
13     @Before("pointcut1()")
14     public void before(){
15         System.out.println("前置通知:第一順位");
16     }
17 }
18 
19 /**
20  * @author 戴著假髮的程式設計師
21  * 
22  * @description
23  */
24 @Component
25 @Aspect
26 @Order(2)//第一順位
27 public class DKAspect2 {
28     @Pointcut("execution(* com.st.dk.demo8.service..*.*(..))")
29     public void pointcut1(){}
30 
31     @Before("pointcut1()")
32     public void before(){
33         System.out.println("前置通知:第二順位");
34     }
35 }
36 
37 /**
38  * @author 戴著假髮的程式設計師
39  * 
40  * @description
41  */
42 @Component
43 @Aspect
44 @Order(3)//第一順位
45 public class DKAspect3 {
46     @Pointcut("execution(* com.st.dk.demo8.service..*.*(..))")
47     public void pointcut1(){}
48 
49     @Before("pointcut1()")
50     public void before(){
51         System.out.println("前置通知:第三順位");
52     }
53 }

測試結果:

注意如果是配置方式實現APO的的通知排序請參考AOP(XML配置)方式的章節。