Spring之@DependsOn注解詳細(xì)解析
1、學(xué)習(xí)指引
Spring創(chuàng)建Bean時(shí)如何指定Bean的依賴順序呢?
在實(shí)際開發(fā)項(xiàng)目的過程中,經(jīng)常會(huì)遇到這樣一種場(chǎng)景:在開發(fā)一個(gè)A功能模塊時(shí),這個(gè)A功能模塊可能會(huì)依賴另一個(gè)B功能模塊。
此時(shí),就需要先開發(fā)B功能模塊,然后在開發(fā)A功能模塊,在A功能模塊中調(diào)用B功能模塊的功能。
在Spring中創(chuàng)建Bean對(duì)象也是如此,可以通過某種方式指定Spring中創(chuàng)建Bean的依賴順序,Spring會(huì)根據(jù)創(chuàng)建Bean的依賴順序來創(chuàng)建對(duì)應(yīng)的Bean對(duì)象。
這個(gè)指定創(chuàng)建Bean依賴順序的注解就是@DependsOn注解。
2、注解說明
@DependsOn注解是Spring中提供的一個(gè)指定Spring創(chuàng)建Bean的依賴順序的注解。
例如,在Spring中需要?jiǎng)?chuàng)建A對(duì)象和B對(duì)象,可以使用@DependsOn注解指定創(chuàng)建A對(duì)象時(shí)依賴B對(duì)象,此時(shí),在Spring中就會(huì)先創(chuàng)建B對(duì)象,然后再創(chuàng)建A對(duì)象。
2.1、注解源碼
@DependsOn注解可以標(biāo)注到類或方法上,可以控制bean的創(chuàng)建、初始化和銷毀方法的執(zhí)行順序。源碼詳見:org.springframework.context.annotation.DependsOn。
/** * @author Juergen Hoeller * @since 3.0 */ @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DependsOn { String[] value() default {}; }
從@DependsOn注解的源碼可以看出,@DependsOn注解是從Spring 3.0版本開始提供的注解。其中,只提供了一個(gè)String數(shù)組類型的value屬性,含義如下所示。
value:表示指定的Bean的唯一標(biāo)識(shí),被指定的Bean會(huì)在Spring創(chuàng)建當(dāng)前Bean之前被創(chuàng)建。
2.2、注解使用場(chǎng)景
@DependsOn注解主要用于指定當(dāng)前Bean對(duì)象所依賴的其他Bean對(duì)象。Spring在創(chuàng)建當(dāng)前Bean之前,會(huì)先創(chuàng)建由@DependsOn注解指定的依賴Bean,在Spring中使用@DependsOn注解的場(chǎng)景通常會(huì)有以下幾種場(chǎng)景:
- 在某些情況下,Bean不是通過屬性或構(gòu)造函數(shù)參數(shù)顯式依賴于另一個(gè)Bean的,但是卻需要在創(chuàng)建一個(gè)Bean對(duì)象之前,需要先創(chuàng)建另一個(gè)Bean對(duì)象,此時(shí)就可以使用@DependsOn注解。
- 在單例Bean的情況下@DependsOn既可以指定初始化依賴順序,也可以指定Bean相應(yīng)的銷毀執(zhí)行順序。
- @DependsOn注解可標(biāo)注到任何直接或間接帶有@Component注解的Bean或標(biāo)注到@Bean注解的方法上,可以控制Bean的創(chuàng)建、初始化和銷毀方法執(zhí)行順序。
- 觀察者模式可以分為事件,事件源和監(jiān)聽器三個(gè)組件,如果在Spring中需要實(shí)現(xiàn)觀察者模式時(shí),就可以使用@DependsOn注解實(shí)現(xiàn)監(jiān)聽器的Bean對(duì)象在事件源的Bean對(duì)象之前被創(chuàng)建。
3、使用案例
Spring的@DependsOn注解可以標(biāo)注到類或方法上,所以,本節(jié)會(huì)列舉@DependsOn注解標(biāo)注到類和方法上兩個(gè)案例
3.1、標(biāo)注到類上的案例
本節(jié),主要使用@DependsOn注解標(biāo)注到類上來實(shí)現(xiàn)Spring創(chuàng)建Bean的依賴順序案例,具體實(shí)現(xiàn)步驟如下所示。
3.1.1、新建DependsOnClassA類
@Component(value = "dependsOnClassA") @DependsOn(value = {"dependsOnClassB"}) public class DependsOnClassA { private final Logger logger = LoggerFactory.getLogger(DependsOnClassA.class); public DependsOnClassA(){ logger.info("執(zhí)行DependsOnClassA的構(gòu)造方法"); } }
可以看到,DependsOnClassA類上使用@Component注解標(biāo)注,并且指定了Bean的名稱為dependsOnClassA,以及使用@DependsOn注解指定了依賴的Bean名稱為dependsOnClassB。
3.1.2、新建DependsOnClassB類
@Component(value = "dependsOnClassB") public class DependsOnClassB { private final Logger logger = LoggerFactory.getLogger(DependsOnClassB.class); public DependsOnClassB(){ logger.info("執(zhí)行DependsOnClassB的構(gòu)造方法"); } }
可以看到,在DependsOnClassB類上標(biāo)注了@Component注解,指定了Bean對(duì)象的名稱為dependsOnClassB。
由DependsOnClassA類和DependsOnClassB類可以看出,在Spring中創(chuàng)建DependsOnClassA類的對(duì)象時(shí),會(huì)依賴DependsOnClassB類的對(duì)象。
所以,在Spring中,創(chuàng)建DependsOnClassA類的對(duì)象之前,會(huì)先創(chuàng)建DependsOnClassB類的對(duì)象
3.1.3、新建DependsOnConfig類
@Configuration @ComponentScan(basePackages = "io.binghe.spring.annotation.chapter07") public class DependsOnConfig { }
可以看到,DependsOnConfig類的實(shí)現(xiàn)比較簡(jiǎn)單,在DependsOnConfig類上標(biāo)注了@Configuration注解,表示這是一個(gè)Spring的配置類,并且使用@ComponentScan注解指定了掃描的基礎(chǔ)包名。
3.1.4、新建DependsOnTest類
public class DependsOnTest { public static void main(String[] args) { new AnnotationConfigApplicationContext(DependsOnConfig.class); } }
可以看到,DependsOnTest類作為測(cè)試案例的啟動(dòng)類,整體實(shí)現(xiàn)比較簡(jiǎn)單,就是在main()方法中創(chuàng)建Spring的IOC容器。
3.1.5、測(cè)試DependsOnTest類
運(yùn)行DependsOnTest類中的main()方法,輸出的結(jié)果信息如下所示。
14:56:17.977 [main] INFO DependsOnClassB - 執(zhí)行DependsOnClassB的構(gòu)造方法
14:56:17.978 [main] INFO DependsOnClassA - 執(zhí)行DependsOnClassA的構(gòu)造方法
可以看到,當(dāng)@DependsOn注解標(biāo)注到類上時(shí),Spring在創(chuàng)建標(biāo)注了@DependsOn注解的類的Bean對(duì)象之前,會(huì)先創(chuàng)建使用@DependsOn注解指定的Bean對(duì)象。
3.2、標(biāo)注到方法上的案例
3.2.1、新建DependsOnMethodA類
public class DependsOnMethodA { private final Logger logger = LoggerFactory.getLogger(DependsOnMethodA.class); public DependsOnMethodA(){ logger.info("執(zhí)行DependsOnMethodA的構(gòu)造方法"); } }
可以看到,DependsOnMethodA類就是一個(gè)簡(jiǎn)單的實(shí)體類,這里不再贅述。
3.2.2、新增DependsOnMethodB類
public class DependsOnMethodB { private final Logger logger = LoggerFactory.getLogger(DependsOnMethodB.class); public DependsOnMethodB(){ logger.info("執(zhí)行DependsOnMethodB的構(gòu)造方法"); } }
可以看到,DependsOnMethodB類就是一個(gè)簡(jiǎn)單的實(shí)體類,這里不再贅述。
3.2.3、修改DependsOnConfig類
在DependsOnConfig類中使用@Bean注解分別創(chuàng)建DependsOnMethodA類和DependsOnMethodB類的Bean對(duì)象,如下所示。
@DependsOn(value = {"dependsOnMethodB"}) @Bean(value = "dependsOnMethodA") public DependsOnMethodA dependsOnMethodA(){ return new DependsOnMethodA(); } @Bean(value = "dependsOnMethodB") public DependsOnMethodB dependsOnMethodB(){ return new DependsOnMethodB(); }
可以看到,在DependsOnConfig類中使用@Bean注解創(chuàng)建DependsOnMethodA類的Bean對(duì)象時(shí),使用@DependsOn注解依賴了名稱為dependsOnMethodB的Bean對(duì)象。
3.2.4、測(cè)試DependsOnTest類
運(yùn)行DependsOnTest類中的main()方法,輸出的結(jié)果信息如下所示。
15:16:24.523 [main] INFO DependsOnClassB - 執(zhí)行DependsOnClassB的構(gòu)造方法
15:16:24.524 [main] INFO DependsOnClassA - 執(zhí)行DependsOnClassA的構(gòu)造方法
15:16:24.528 [main] INFO DependsOnMethodB - 執(zhí)行DependsOnMethodB的構(gòu)造方法
15:16:24.529 [main] INFO DependsOnMethodA - 執(zhí)行DependsOnMethodA的構(gòu)造方法
可以看到,當(dāng)@DependsOn注解標(biāo)注到方法上時(shí),Spring在執(zhí)行標(biāo)注了@DependsOn注解的方法創(chuàng)建Bean對(duì)象前,先執(zhí)行其他方法來創(chuàng)建使用@DependsOn注解指定的Bean對(duì)象。
通過上述兩個(gè)案例得知:@DependsOn注解可以指定Spring中Bean對(duì)象創(chuàng)建的依賴順序,并且Spring在創(chuàng)建當(dāng)前Bean之前,會(huì)先創(chuàng)建由@DependsOn注解指定的依賴Bean
到此這篇關(guān)于Spring之@DependsOn注解詳細(xì)解析的文章就介紹到這了,更多相關(guān)@DependsOn注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java語言實(shí)現(xiàn)簡(jiǎn)單FTP軟件 輔助功能模塊FTP站點(diǎn)管理實(shí)現(xiàn)(12)
這篇文章主要為大家詳細(xì)介紹了Java語言實(shí)現(xiàn)簡(jiǎn)單FTP軟,輔助功能模塊FTP站點(diǎn)管理的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04Java線程狀態(tài)及切換、關(guān)閉線程的正確姿勢(shì)分享
這篇文章主要給大家介紹了關(guān)于Java線程狀態(tài)及切換、關(guān)閉線程的正確姿勢(shì),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10java數(shù)據(jù)結(jié)構(gòu)關(guān)于棧的實(shí)例應(yīng)用
大家好,本篇文章主要講的是java數(shù)據(jù)結(jié)構(gòu)關(guān)于棧的實(shí)例應(yīng)用,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12JavaFX實(shí)現(xiàn)簡(jiǎn)易時(shí)鐘效果(二)
這篇文章主要為大家詳細(xì)介紹了JavaFX實(shí)現(xiàn)簡(jiǎn)易時(shí)鐘效果的第二篇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11java使用單向鏈表解決數(shù)據(jù)存儲(chǔ)自定義排序問題
本文主要介紹了java使用單向鏈表解決數(shù)據(jù)存儲(chǔ)自定義排序問題,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03SpringBoot FreeWorker模板技術(shù)解析
這篇文章主要介紹了SpringBoot FreeWorker模板技術(shù)解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11關(guān)于spring中單例Bean引用原型Bean產(chǎn)生的問題及解決
這篇文章主要介紹了關(guān)于spring中單例Bean引用原型Bean產(chǎn)生的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06InputStreamReader 和FileReader的區(qū)別及InputStream和Reader的區(qū)別
這篇文章主要介紹了InputStreamReader 和FileReader的區(qū)別及InputStream和Reader的區(qū)別的相關(guān)資料,需要的朋友可以參考下2015-12-12