Spring高級(jí)注解之@DependsOn詳解
官方文檔
Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. Used infrequently in cases where a bean does not explicitly depend on another through properties or constructor arguments, but rather depends on the side effects of another bean's initialization. A depends-on declaration can specify both an initialization-time dependency and, in the case of singleton beans only, a corresponding destruction-time dependency. Dependent beans that define a depends-on relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. Thus, a depends-on declaration can also control shutdown order. May be used on any class directly or indirectly annotated with org.springframework.stereotype.Component or on methods annotated with Bean. Using DependsOn at the class level has no effect unless component-scanning is being used. If a DependsOn-annotated class is declared via XML, DependsOn annotation metadata is ignored, and <bean depends-on="..."/> is respected instead.
@DependsOn注解的作用
org.springframework.context.annotation.DependsOn該注解的屬性是一個(gè)字符串?dāng)?shù)組,數(shù)組的元素是每個(gè)依賴(lài)的bean的名稱(chēng)。
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DependsOn { String[] value() default {}; }
@DependsOn注解主要用于指定當(dāng)前bean所依賴(lài)的beans。任何被指定依賴(lài)的bean都由Spring保證在當(dāng)前bean之前創(chuàng)建。在少數(shù)情況下,bean不是通過(guò)屬性或構(gòu)造函數(shù)參數(shù)顯式依賴(lài)于另一個(gè)bean,但卻需要要求另一個(gè)bean優(yōu)先完成初始化,則可以使用@DependsOn這個(gè)注解。
@DependsOn既可以指定初始化依賴(lài)順序,也可以指定bean相應(yīng)的銷(xiāo)毀執(zhí)行順序(僅在單例bean的情況下)。
可用于任何直接或間接帶@Component注解的bean或在用@Bean注釋的方法上。 如果使用的是xml配置,則需要使用<bean dependens on=“…”/>標(biāo)簽.
簡(jiǎn)單描述就是@DependsOn可以控制bean的創(chuàng)建、初始化(InitializingBean)、銷(xiāo)毀方法執(zhí)行順序。
示例:假如有三個(gè)Bean類(lèi)叫Aaa、Bbb、Ccc分別實(shí)現(xiàn)了如下兩個(gè)接口。org.springframework.beans.factory.InitializingBeanorg.springframework.beans.factory.DisposableBean
Ccc通過(guò)@DependsOn指定依賴(lài)bean創(chuàng)建的順序?yàn)锽bb > Aaa
@DependsOn({"bbb","ccc"}) @Service public class Aaa implements InitializingBean, DisposableBean { private static final Logger logger = LoggerFactory.getLogger(Aaa.class); public Aaa() { logger.info(this.getClass().getName() + " Construction"); } @Override public void afterPropertiesSet() throws Exception { logger.info(this.getClass().getName() + " afterPropertiesSet"); } @Override public void destroy() throws Exception { logger.info(this.getClass().getName() + " destroy"); } }
Bbb Ccc類(lèi)實(shí)現(xiàn)如下
@Service public class Bbb implements InitializingBean, DisposableBean { //實(shí)現(xiàn)和Aaa相同 } @Service public class Ccc implements InitializingBean, DisposableBean { //實(shí)現(xiàn)和Aaa相同 }
那么初始順序如下: bbb --> ccc --> aaa
而銷(xiāo)毀方法執(zhí)行順序正好相反如下: aaa --> ccc --> bbb
@DependsOn注解的實(shí)現(xiàn)原理
Spring在啟動(dòng)時(shí)掃描到一個(gè)bean,會(huì)封裝成一個(gè)BeanDefinition,如果是AnnotatedBeanDefinition則解析類(lèi)上的注解信息,發(fā)現(xiàn)@DependsOn注解,則讀取value值,調(diào)用BeanDefinition#setDependsOn保存。 源碼見(jiàn)ClassPathBeanDefinitionScanner#doScan,AnnotationConfigUtils#processCommonDefinitionAnnotations(AnnotatedBeanDefinition, AnnotatedTypeMetadata)
創(chuàng)建bean時(shí),也就是調(diào)用AbstractBeanFactory#doGetBean時(shí),會(huì)獲取這些被依賴(lài)的beanName,按照數(shù)組順序,再調(diào)用AbstractBeanFactory#getBean(beanName)來(lái)優(yōu)先創(chuàng)建被依賴(lài)的bean,從而達(dá)到控制依賴(lài)順序。
除此之外,在創(chuàng)建bean時(shí),還會(huì)調(diào)用AbstractBeanFactory#registerDisposableBeanIfNecessary來(lái)向Spring中注冊(cè)帶有銷(xiāo)毀方法的bean,源碼見(jiàn)DefaultSingletonBeanRegistry#registerDisposableBean,內(nèi)部通過(guò)LinkedHashMap保存。key為bean名稱(chēng)。進(jìn)程退出時(shí),會(huì)逆序調(diào)用銷(xiāo)毀方法。 源碼見(jiàn)DefaultSingletonBeanRegistry#destroySingletons
public void destroySingletons() { if (logger.isTraceEnabled()) { logger.trace("Destroying singletons in " + this); } synchronized (this.singletonObjects) { this.singletonsCurrentlyInDestruction = true; } String[] disposableBeanNames; synchronized (this.disposableBeans) { disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet()); } for (int i = disposableBeanNames.length - 1; i >= 0; i--) { destroySingleton(disposableBeanNames[i]); } this.containedBeanMap.clear(); this.dependentBeanMap.clear(); this.dependenciesForBeanMap.clear(); clearSingletonCache(); }
到此這篇關(guān)于Spring高級(jí)注解之@DependsOn詳解的文章就介紹到這了,更多相關(guān)@DependsOn詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis模糊查詢(xún)之三種定義參數(shù)方法和聚合查詢(xún)、主鍵回填實(shí)現(xiàn)方法
這篇文章主要介紹了Mybatis模糊查詢(xún)之三種定義參數(shù)方法和聚合查詢(xún)、主鍵回填實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03springboot實(shí)現(xiàn)的https單向認(rèn)證和雙向認(rèn)證(java生成證書(shū))
springboot https單向認(rèn)證和雙向認(rèn)證,本文主要介紹了springboot實(shí)現(xiàn)的https單向認(rèn)證和雙向認(rèn)證,具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04java調(diào)用webservice的.asmx接口的使用步驟
這篇文章主要介紹了java調(diào)用webservice的.asmx接口的使用步驟,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09Spring?security?oauth2以redis作為tokenstore及jackson序列化失敗問(wèn)題
這篇文章主要介紹了Spring?security?oauth2以redis作為tokenstore及jackson序列化失敗問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教<BR>2024-04-04Mybatis-Plus之ID自動(dòng)增長(zhǎng)的設(shè)置實(shí)現(xiàn)
本文主要介紹了Mybatis-Plus之ID自動(dòng)增長(zhǎng)的設(shè)置實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07JAVA8 stream中三個(gè)參數(shù)的reduce方法對(duì)List進(jìn)行分組統(tǒng)計(jì)操作
這篇文章主要介紹了JAVA8 stream中三個(gè)參數(shù)的reduce方法對(duì)List進(jìn)行分組統(tǒng)計(jì)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08Spring數(shù)據(jù)庫(kù)多數(shù)據(jù)源路由配置過(guò)程圖解
這篇文章主要介紹了Spring數(shù)據(jù)庫(kù)多數(shù)據(jù)源路由配置過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06