SpringBoot控制配置類加載順序方式
SpringBoot控制配置類加載順序
@Configuration配置被加載進(jìn)容器的方式大體上可分為3種
- 手動(dòng):構(gòu)建ApplicationContext時(shí)由構(gòu)建者手動(dòng)傳入,可手動(dòng)控制順序。
- 自動(dòng)1:被@ComponentScan自動(dòng)掃描進(jìn)去,無(wú)法控制順序。
- 自動(dòng)2:自動(dòng)掃描,運(yùn)用SpringBoot的3大注解,可以控制順序。
控制配置類加載順序
2.1、傳統(tǒng)的 Spring Framework 控制配置類加載順序
在傳統(tǒng)的 Spring Framework 里,一個(gè) @Configuration 注解標(biāo)注的類就代表一個(gè)配置類,當(dāng)存在多個(gè) @Configuration 時(shí),他們的執(zhí)行順序是由使用者靠手動(dòng)指定的,就像這樣:
// 手動(dòng)控制Config1 Config2的順序 ApplicationContext context = new AnnotationConfigApplicationContext(Config1.class, Config2.class);
2.2、SpringBoot 控制配置類加載順序
第一步:把 A_SonConfig 和 B_ParentConfig 挪動(dòng)到 Application 掃描不到的包內(nèi),切記:一定且必須是掃描不到的包內(nèi)(可以放到啟動(dòng)類掃描不到的目錄)。
第二步:當(dāng)前工程里增加配置META-INF/spring.factories,內(nèi)容為(配置里Son和Parent前后順序?qū)Y(jié)果無(wú)影響):
org.springframework.boot.autoconfigure.EnableAutoConfiguration=x.A_SonConfig,x.B_ParentConfig
第三步:通過 SpringBoot 自動(dòng)配置順序相關(guān)的三大注解 @AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder作用于自動(dòng)配置類。
@AutoConfigureBefore(A_SonConfig.class) @Configuration public class B_ParentConfig { ? ? B_ParentConfig() { ? ? ? ? System.out.println("配置類ParentConfig構(gòu)造器被執(zhí)行..."); ? ? } }
注意:
SpringBoot 自動(dòng)配置三大注解不能作用于被啟動(dòng)類掃描的配置類中。
Spring Boot的自動(dòng)配置均是通過spring.factories來指定的,它的優(yōu)先級(jí)最低(執(zhí)行時(shí)機(jī)是最晚的);通過掃描進(jìn)來的優(yōu)先級(jí)是最高的。
Spring Boot的自動(dòng)配置是通過@EnableAutoConfiguration注解驅(qū)動(dòng)的,默認(rèn)是開啟狀態(tài)。你也可以通過spring.boot.enableautoconfiguration = false來關(guān)閉它,回退到Spring Framework時(shí)代。
如何正確控制springboot中bean的加載順序
為什么需要控制加載順序
springboot遵從約定大于配置的原則,極大程度的解決了配置繁瑣的問題。在此基礎(chǔ)上,又提供了spi機(jī)制,用spring.factories可以完成一個(gè)小組件的自動(dòng)裝配功能。
在一般業(yè)務(wù)場(chǎng)景,可能你不大關(guān)心一個(gè)bean是如何被注冊(cè)進(jìn)spring容器的。只需要把需要注冊(cè)進(jìn)容器的bean聲明為@Component即可,spring會(huì)自動(dòng)掃描到這個(gè)Bean完成初始化并加載到spring上下文容器。
而當(dāng)你在項(xiàng)目啟動(dòng)時(shí)需要提前做一個(gè)業(yè)務(wù)的初始化工作時(shí),或者你正在開發(fā)某個(gè)中間件需要完成自動(dòng)裝配時(shí)。你會(huì)聲明自己的Configuration類,但是可能你面對(duì)的是好幾個(gè)有互相依賴的Bean。如果不加以控制,這時(shí)候可能會(huì)報(bào)找不到依賴的錯(cuò)誤。
但是你明明已經(jīng)把相關(guān)的Bean都注冊(cè)進(jìn)spring上下文了呀。這時(shí)候你需要通過一些手段來控制springboot中的bean加載順序。
幾個(gè)誤區(qū)
在正式說如何控制加載順序之前,先說2個(gè)誤區(qū)。
在標(biāo)注了@Configuration的類中,寫在前面的@Bean一定會(huì)被先注冊(cè)
這個(gè)不存在的,spring在以前xml的時(shí)代,也不存在寫在前面一定會(huì)被先加載的邏輯。因?yàn)閤ml不是漸進(jìn)的加載,而是全部parse好,再進(jìn)行依賴分析和注冊(cè)。到了springboot中,只是省去了xml被parse成spring內(nèi)部對(duì)象的這一過程,但是加載方式并沒有大的改變。
利用@Order這個(gè)標(biāo)注能進(jìn)行加載順序的控制
嚴(yán)格的說,不是所有的Bean都可以通過@Order這個(gè)標(biāo)注進(jìn)行順序的控制。你把@Order這個(gè)標(biāo)注加在普通的方法上或者類上一點(diǎn)鳥用都沒有。
那@Order能控制哪些bean的加載順序呢,我們先看看官方的解釋:
最開始@Order注解用于切面的優(yōu)先級(jí)指定;在 4.0 之后對(duì)它的功能進(jìn)行了增強(qiáng),支持集合的注入時(shí),指定集合中 bean 的順序,并且特別指出了,它對(duì)于當(dāng) 實(shí)例的 bean 之間的順序,沒有任何影響。
目前用的比較多的有以下3點(diǎn):
- 控制AOP的類的加載順序,也就是被@Aspect標(biāo)注的類
- 控制ApplicationListener實(shí)現(xiàn)類的加載順序
- 控制CommandLineRunner實(shí)現(xiàn)類的加載順序
如何控制
1.@DependsOn
@DependsOn注解可以用來控制bean的創(chuàng)建順序,該注解用于聲明當(dāng)前bean依賴于另外一個(gè)bean。所依賴的bean會(huì)被容器確保在當(dāng)前bean實(shí)例化之前被實(shí)例化。
示例:
以上代碼bean的加載順序?yàn)椋?/p>
@DependsOn的使用:
直接或者間接標(biāo)注在帶有@Component注解的類上面;
直接或者間接標(biāo)注在帶有@Bean注解的方法上面;
使用@DependsOn注解到類層面僅僅在使用 component-scanning 方式時(shí)才有效,如果帶有@DependsOn注解的類通過XML方式使用,該注解會(huì)被忽略,<bean depends-on="..."/>這種方式會(huì)生效。
2.參數(shù)注入
在@Bean標(biāo)注的方法上,如果你傳入了參數(shù),springboot會(huì)自動(dòng)會(huì)為這個(gè)參數(shù)在spring上下文里尋找這個(gè)類型的引用。并先初始化這個(gè)類的實(shí)例。
利用此特性,我們也可以控制bean的加載順序。
示例:
以上結(jié)果,beanB先于beanA被初始化加載。
需要注意的是,springboot會(huì)按類型去尋找。如果這個(gè)類型有多個(gè)實(shí)例被注冊(cè)到spring上下文,那你就需要加上@Qualifier("Bean的名稱")來指定
3.利用bean的生命周期中的擴(kuò)展點(diǎn)
在spring體系中,從容器到Bean實(shí)例化&初始化都是有生命周期的,并且提供了很多的擴(kuò)展點(diǎn),允許你在這些步驟時(shí)進(jìn)行邏輯的擴(kuò)展。
這些可擴(kuò)展點(diǎn)的加載順序由spring自己控制,大多數(shù)是無(wú)法進(jìn)行干預(yù)的。我們可以利用這一點(diǎn),擴(kuò)展spring的擴(kuò)展點(diǎn)。在相應(yīng)的擴(kuò)展點(diǎn)加入自己的業(yè)務(wù)初始化代碼。從來達(dá)到順序的控制。
4.@AutoConfigureOrder
這個(gè)注解用來指定配置文件的加載順序。但是在實(shí)際測(cè)試中發(fā)現(xiàn),以下這樣使用是不生效的:
無(wú)論你2個(gè)數(shù)字填多少,都不會(huì)改變其加載順序結(jié)果。
那這個(gè)@AutoConfigureOrder到底是如何使用的呢。
經(jīng)過測(cè)試發(fā)現(xiàn),@AutoConfigureOrder只能改變外部依賴的@Configuration的順序。如何理解是外部依賴呢。
能被你工程內(nèi)部scan到的包,都是內(nèi)部的Configuration,而spring引入外部的Configuration,都是通過spring特有的spi文件:spring.factories
換句話說,@AutoConfigureOrder能改變spring.factories中的@Configuration的順序。
具體使用方式:
spring.factories:
心得:
其實(shí)在工作中,我相信很多人碰到過復(fù)雜的依賴關(guān)系的bean加載,把這種不確定性交給spring去做,還不如我們自己去控制,這樣在閱讀代碼的時(shí)候 ,也能輕易看出bean之間的依賴先后順序。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- SpringBoot配置文件的優(yōu)先級(jí)順序、加載順序、bootstrap.yml與application.yml區(qū)別及說明
- SpringBoot的配置文件application.yml及加載順序詳解
- SpringBoot調(diào)整ApplicationContextAware如何實(shí)現(xiàn)類加載順序
- springboot中的靜態(tài)資源加載順序優(yōu)先級(jí)
- 如何正確控制springboot中bean的加載順序小結(jié)篇
- 詳解Spring Boot 配置加載順序及屬性加載順序
- Spring?Boot?配置文件之類型、加載順序與最佳實(shí)踐記錄
相關(guān)文章
java版微信公眾平臺(tái)消息接口應(yīng)用示例
這篇文章主要介紹了java版微信公眾平臺(tái)消息接口應(yīng)用,結(jié)合實(shí)例形式對(duì)比分析了PHP與java應(yīng)用微信公眾平臺(tái)接口的相關(guān)調(diào)用與操作技巧,需要的朋友可以參考下2017-07-07Springboot使用JustAuth實(shí)現(xiàn)各種第三方登陸
本文主要介紹了Springboot使用JustAuth實(shí)現(xiàn)各種第三方登陸,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07Java中checkbox實(shí)現(xiàn)跨頁(yè)多選的方法
最近做了一個(gè)項(xiàng)目其中遇到這樣的需求,要實(shí)現(xiàn)checkbox跨頁(yè)多選功能,經(jīng)過小編整理,順利解決,今天小編給大家分享Java中checkbox實(shí)現(xiàn)跨頁(yè)多選的方法,需要的的朋友參考下2017-01-01Java高并發(fā)場(chǎng)景下的 HttpClient請(qǐng)求優(yōu)化實(shí)現(xiàn)
本文主要介紹了Java高并發(fā)場(chǎng)景下的 HttpClient請(qǐng)求優(yōu)化實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01HTTP基本認(rèn)證(Basic Authentication)的JAVA實(shí)例代碼
下面小編就為大家?guī)硪黄狧TTP基本認(rèn)證(Basic Authentication)的JAVA實(shí)例代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11Mybatis 一級(jí)緩存與二級(jí)緩存的實(shí)現(xiàn)
mybatis作為一個(gè)流行的持久化工具,緩存必然是缺少不了的組件。通過這篇文章,就讓我們來了解一下一級(jí)緩存與二級(jí)緩存的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05測(cè)量Java對(duì)象所占內(nèi)存大小方式
這篇文章主要介紹了測(cè)量Java對(duì)象所占內(nèi)存大小方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09