@order
注解是spring-core
包下的一個注解,@Order
的作用是定義Spring IOC容器中Bean的執(zhí)行順序的優(yōu)先級(這里的順序也可以理解為存放到容器中的先后順序)。開發(fā)過程當中有時候經(jīng)常會出現(xiàn)配置依賴關系,例如注入A對象使用了@ConditionalOnBean(B.class)
,意思是要求容器當中必須存在B.class
的實例的時候,才會進行注入A
。這時候我們就必須保證B對象在注入A
對象前進行注入。
(1)源碼當中有三個元注解:
(2)屬性:
@order當中只要一個value屬性,而且還是int類型,值越低優(yōu)先級越高,默認值是Ordered.LOWEST_PRECEDENCE
,表示最低優(yōu)先級(輸給任何其他指定的順序值)。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
public @interface Order {int value() default 2147483647;
}
官網(wǎng)注釋:https://github.com/spring-projects/spring-framework/blob/main/spring-core/src/main/java/org/springframework/core/annotation/Order.java
二、@order實戰(zhàn)(1)自定義兩個配置類
我們要求Config2先進行加載,然后通過@order來排序測試一下
@Configuration
public class Config1 {public Config1() {System.out.println("Config1構建了");
}
}
@Configuration
public class Config2 {public Config2() {System.out.println("Config2構建了");
}
}
(2)啟動項目測試:默認是先創(chuàng)建的Config1后創(chuàng)建的Config2
(3)既然order可以控制加載順序,那我們來試驗一下,然后讓Config2 先加載
@Configuration
@Order(2)
public class Config1 {public Config1() {System.out.println("Config1構建了");
}
}
@Configuration
@Order(1)
public class Config2 {public Config2() {System.out.println("Config2構建了");
}
}
但是好像沒什么卵用
(4)分析原因
目前這兩個是在同包情況下不起作用。
于是進行分開了
分開之后竟然生效了
(5)但是分開也是將Config2放到了上面的包當中,于是我又改成了Config1放到最上面,這樣進行測試,結果又失效了
(6)于是我又放在了同包下,將Config2命名為A開頭的,這樣他就放到了最上面,于是這樣同樣也生效了。
期間我還嘗試著將@Configuration都改為使用@Component,結果仍然不變。
得出結論:
@order
指定加載順序還跟類的命名和存放位置有關!假如有Config1
和Config2
兩個類在一個包下,要求是Config2
先加載:
Config2
的@order值
就算是小于Config1
的@order值
同樣也是Config1
先加載。這樣才能保證@Order生效!
三、@order失效原因https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-constructor-injection
最關鍵的一句話:您可以在目標類級別和@Bean方法上聲明@Order注釋,可能針對的是單個bean定義(如果多個定義使用同一個bean類)。@Order值可能會影響注入點的優(yōu)先級,但請注意,它們不會影響單例啟動順序
,這是由依賴關系和@DependsOn聲明確定的正交關注。
我理解的注入點的優(yōu)先級應該是指的存放容器的先后順序,也就是他并不會影響啟動順序。
四、解決排序問題我們不可能每次遇到這種問題又是改名又是換包的,所以,springboot提供了如下三個注解可以控制順序:
(1)首先將代碼改回原來的樣子
(2)在Config2使用@AutoConfigureBefore(Config1.class),代表的是在config1加載前進行加載
@Configuration
public class Config1 {public Config1() {System.out.println("Config1構建了");
}
}
@Configuration
@AutoConfigureBefore(Config1.class)
public class Config2 {public Config2() {System.out.println("Config2構建了");
}
}
(3)輸出結果,顯然還是沒生效
可能有時候走了狗屎運給你一種錯覺還真的配置成功了。實際上這種方式是不可行的,以上三個注解只有針對
自動配置類
才會生效。
在autoconfigure包下就有spring.factories,這個文件配置了自動配置類,springboot會讀取這個文件的,我們也可以在自己項目上定義spring.factories,這樣我們的配置類對于@AutoConfigureAfter注解就可以生效了。
(4)自定義spring.factories
第一行是固定的,后面的就是全類名,雖然只有Config2使用了注解,但是需求是和Config1進行排序,所以這兩個都得加。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.gzl.cn.springbootcache.config.Config2,\
com.gzl.cn.springbootcache.config.Config1
(5)測試,成功解決
五、排序源碼分析針對于@AutoConfigure那三個注解原理:其實關鍵的代碼還是在AutoConfigurationImportSelector中,將自動配置類從spring.factories加載出來之后會根據(jù)條件排序(只有自動配置類!),在selectImports()方法中最后一行代碼如下:
緊接著會走到這個地方,實際上是分了三步排序:
從上面配置的順序可以知道,最終決定權還是在@AutoConfigureAfter、@AutoConfigureBefore這兩個注解。
當我們不設置spring.factories的時候,這里面壓根都沒有這兩個類!
六、@AutoConfigureOrder這種也是可以的!當然前提也是需要配置spring.factories
@Configuration
@AutoConfigureOrder(2)
public class Config1 {public Config1() {System.out.println("Config1構建了");
}
}
@Configuration
@AutoConfigureOrder(1)
public class Config2 {public Config2() {System.out.println("Config2構建了");
}
}
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
分享題目:@order注解用法-創(chuàng)新互聯(lián)
網(wǎng)站地址:http://vcdvsql.cn/article20/csipco.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內鏈、網(wǎng)站制作、商城網(wǎng)站、手機網(wǎng)站建設、云服務器、網(wǎng)頁設計公司
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)