Spring中@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
該注解的屬性是一個字串陣列,陣列的元素是每個依賴的bean的名稱,
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DependsOn {
String[] value() default {};
}
@DependsOn注解主要用于指定當前bean所依賴的beans,任何被指定依賴的bean都由Spring保證在當前bean之前創建,在少數情況下,bean不是通過屬性或建構式引數顯式依賴于另一個bean,但卻需要要求另一個bean優先完成初始化,則可以使用@DependsOn這個注解,
@DependsOn既可以指定初始化依賴順序,也可以指定bean相應的銷毀執行順序(僅在單例bean的情況下),
可用于任何直接或間接帶@Component注解的bean或在用@Bean注釋的方法上,
如果使用的是xml配置,則需要使用<bean dependens on=“…”/>標簽.
簡單描述就是@DependsOn可以控制bean的執行創建、初始化(InitializingBean)、銷毀方法執行順序,
示例:假如有三個Bean類叫Aaa、Bbb、Ccc分別實作了
org.springframework.beans.factory.InitializingBean
org.springframework.beans.factory.DisposableBean
兩個介面,
Ccc通過@DependsOn指定依賴bean創建的順序為Bbb > 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類實作如下
@Service
public class Bbb implements InitializingBean, DisposableBean {
//實作和Aaa相同
}
@Service
public class Ccc implements InitializingBean, DisposableBean {
//實作和Aaa相同
}
那么初始順序如下: bbb --> ccc --> aaa

而銷毀方法執行順序正好相反如下: aaa --> ccc --> bbb

@DependsOn注解的實作原理
Spring在啟動是掃描到一個bean,會封裝成一個BeanDefinition,如果是AnnotatedBeanDefinition則決議類上的注解資訊,發現@DependsOn注解,則讀取value值,呼叫BeanDefinition#setDependsOn保存,
原始碼見ClassPathBeanDefinitionScanner#doScan,AnnotationConfigUtils#processCommonDefinitionAnnotations(AnnotatedBeanDefinition, AnnotatedTypeMetadata)
創建bean時,也就是呼叫AbstractBeanFactory#doGetBean時,會獲取這些被依賴的,按照陣列順序,再呼叫AbstractBeanFactory#getBean(beanName)來優先創建被依賴的bean,從而達到控制依賴順序,
除此之外,在創建bean時,還有呼叫AbstractBeanFactory#registerDisposableBeanIfNecessary來向Spring中注冊帶有銷毀方法的bean,原始碼見DefaultSingletonBeanRegistry#registerDisposableBean,內部通過LinkedHashMap保存,key為bean名稱,行程退出時,會逆序呼叫銷毀方法,
原始碼見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();
}
今天大年三十,祝大家新年快樂!!!財源廣進!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/259218.html
標籤:java
上一篇:java多執行緒總結
