Spring中@DependsOn的原理

前言

在工程中用到了@DependsOn这个注解,大致了解了一下其实现原理。

正文

Spring 中,如果想要实现 “BeanA 要在 BeanB 和 BeanC 构造完成后才构造” 这样的场景的话,需要在 BeanA 中加入@DependsOn({"beanB", "beanC"}),这样的注解,这样Spring就能确保”beanB”, “beanC”先构造完成。

那么,Spring是怎么实现得呢?十分简单,简言之就是当在构造”beanA”的过程中发现其标注有@DependsOn的话,就会先调用一遍其中指定的beans的构造流程。代码也比较简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

...

// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) { // 循环所有 dependsOn 的 bean名
if (isDependent(beanName, dep)) { // 校验一下是否存在循环所 dependsOn,循环dependsOn是不允许的
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName); // 注册dependsOn关系,用于上边校验循环dependsOn用
try {
getBean(dep); // 让被依赖的bean先走构造流程
}
catch (NoSuchBeanDefinitionException ex) { // 用被依赖的bean名无法构造bean需要抛出异常
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

...

}