@DependOn注解说明:
1:在Spring的bean定义抽象类 AbstractBeanDefinition 里,属性 dependsOn 存放类的依赖bean。
2:方法 AnnotationConfigUtils#processCommonDefinitionAnnotations(AnnotatedBeanDefinition, AnnotatedTypeMetadata) 里解析处理常用的在类上的注解,比如:@Primary,@Lazy,@DependsOn等,通过该方法dependsOn属性赋值。给代码如下:
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
......
if (metadata.isAnnotated(DependsOn.class.getName())) {
abd.setDependsOn(attributesFor(metadata,DependsOn.class).getStringArray("value"));
}
......
}
3:核心方法 AbstractApplicationContext.refresh() 里面,会调用方法 AbstractBeanFactory#doGetBean 获取注册实例,其里面会处理DenpendOn,如下:
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 获取上面第二部获取到的DependOn配置,如果不为空,就进行检查
String[] dependsOn = mbd.getDependsOn();
if (dependsOn !=null) {
for (String dep : dependsOn) {
// 检查是否有循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName +"' and '" + dep +"'");
}
// 添加依赖项信息到缓存。
// 这里有2个缓存,加入实例A依赖于实例B,则缓存如下:
// dependentBeanMap 的KEY是B,存储方式为 B ->A
// dependenciesForBeanMap 的KEY是A,存放方式是 A->B
registerDependentBean(dep, beanName);
try {
// 获取依赖的bean,如果不存在,则创建
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName +"' depends on missing bean '" + dep +"'", ex);
}
}
}
// 依赖项目检查方法,其递归从dependentBeanMap缓存中检查依赖性是否存在循环依赖。
// 加入 实例A依赖于实例B,则 dependentBeanMap 存放的KEY是B,B->A的方式存储。
private boolean isDependent(String beanName, String dependentBeanName, Set alreadySeen) {
if (alreadySeen !=null && alreadySeen.contains(beanName)) {
return false;
}
String canonicalName = canonicalName(beanName);
Set dependentBeans =this.dependentBeanMap.get(canonicalName);
if (dependentBeans ==null) {
return false;
}
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
for (String transitiveDependency : dependentBeans) {
if (alreadySeen ==null) {
alreadySeen =new HashSet();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
所以,在平时听到的Spring解决循环依赖问题只是针对@Autowire注解。对于@DependOn注解,存在循环依赖还是会报错的(抛出BeanCreationException异常)。