先说结论,因为带构造器产生依赖循环使不会把 bean 放进 earlySingletonObjects,导致 singletonObjects 一直为空后报错,所以使用构造器注入可以检测依赖循环。以下是详细的分析过程。
预备
给以下几个重要的方法设置断点
以下的方法都在 DefaultSingletonBeanRegistry 类里
getSingleton(String beanName, boolean allowEarlyReference)
addSingleton(String beanName, Object singletonObject)
addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)
getSingleton(String beanName, ObjectFactory<?> singletonFactory)
beforeSingletonCreation(String beanName)
afterSingletonCreation(String beanName)
给每个断点添加条件
beanName.equals("wife") || beanName.equals("husband") || beanName.equals("singleDog") || beanName.equals("blindman")
需要关注的变量
依赖注入正常流程
@Autowired 注入
前提
谁被依赖
@Component
public class SingleDog {
}
谁需要依赖其他 bean
@Component
public class Blindman {
@Autowired
SingleDog singleDog;
}
过程
doGetBeanNamesForType() 内 allowEarlyReference 为 false
blindman 走 getSingleton(String beanName, boolean allowEarlyReference)
-
判断
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
返回
-
null
-
-
singleDog 走 getSingleton(String beanName, boolean allowEarlyReference)
-
判断
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
返回
-
null
-
-
doGetBean() 内 allowEarlyReference 为 true
- blindman 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
-
blindman 走 getSingleton(String beanName, boolean allowEarlyReference)
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
blindman 走 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
-
判断
-
singletonObjects 无
-
-
blindman 走 beforeSingletonCreation(String beanName)
-
singletonsCurrentlyInCreation:{"blindman"}
-
-
blindman 走 createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- blindman 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- blindman 走 createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- blindman 走 addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)
-
结果
-
singletonFactories:{"blindman"} earlySingletonObjects:{} registeredSingletons:{"blindman",...}
-
-
blindman 走 populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) 进入遍历执行 InstantiationAwareBeanPostProcessor 对象的 postProcessProperties() 方法
- singleDog 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
-
singleDog 走 getSingleton(String beanName, boolean allowEarlyReference)
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
singleDog 走 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
-
判断
-
singletonObjects 无
-
-
singleDog 走 beforeSingletonCreation(String beanName)
-
singletonsCurrentlyInCreation:{"blindman","singleDog"}
-
-
singleDog 走 createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- singleDog 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- singleDog 走 createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- singleDog 走 addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)
-
结果
-
singletonFactories:{"blindman","singleDog"} earlySingletonObjects:{} registeredSingletons:{"blindman","singleDog",...}
-
-
- singleDog 走 populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)
- singleDog 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
-
singleDog 走 afterSingletonCreation(String beanName)
-
结果
-
singletonsCurrentlyInCreation:{"blindman"}
-
-
-
singleDog 走 addSingleton(String beanName, Object singletonObject)
-
结果
-
singletonObjects:{"singleDog"} singletonFactories:{"blindman"} registeredSingletons:{"blindman","singleDog",...}
-
-
-
-
- singleDog 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
-
- blindman 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
-
blindman 走 afterSingletonCreation(String beanName)
-
结果
-
singletonsCurrentlyInCreation:{}
-
-
-
blindman 走 addSingleton(String beanName, Object singletonObject)
-
结果
-
singletonObjects:{"singleDog","blindman"} singletonFactories:{} registeredSingletons:{"blindman","singleDog",...}
-
-
-
-
测试数据
构造器注入
前提
谁被依赖
@Component
public class SingleDog {
}
谁需要依赖其他 bean
@Component
public class Blindman {
private final SingleDog singleDog;
@Autowired
public Blindman(SingleDog singleDog) {
this.singleDog = singleDog;
}
}
过程
doGetBeanNamesForType() 内 allowEarlyReference 为 false
- singleDog 走 getSingleton(String beanName, boolean allowEarlyReference)
-
判断
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
返回
-
null
-
-
- blindman 走 getSingleton(String beanName, boolean allowEarlyReference)
-
判断
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
返回
-
null
-
-
doGetBean() 内 allowEarlyReference 为 true
- blindman 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
-
blindman 走 getSingleton(String beanName, boolean allowEarlyReference)
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
blindman 走 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
-
判断
-
singletonObjects 无
-
-
blindman 走 beforeSingletonCreation(String beanName)
-
singletonsCurrentlyInCreation:{"blindman"}
-
-
blindman 走 createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- blindman 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- blindman 走 createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- singleDog 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
-
singleDog 走 getSingleton(String beanName, boolean allowEarlyReference)
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
singleDog 走 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
-
判断
-
singletonObjects 无
-
-
singleDog 走 beforeSingletonCreation(String beanName)
-
singletonsCurrentlyInCreation:{"blindman","singleDog"}
-
-
singleDog 走 createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- singleDog 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- singleDog 走 createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- singleDog 走 addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)
-
结果
-
singletonFactories:{"singleDog"} earlySingletonObjects:{} registeredSingletons:{"singleDog",...}
-
-
- singleDog 走 populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)
- singleDog 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
-
singleDog 走 afterSingletonCreation(String beanName)
- 结果
*
singletonsCurrentlyInCreation:{"blindman"}
- 结果
*
-
singleDog 走 addSingleton(String beanName, Object singletonObject)
-
结果
-
singletonObjects:{"singleDog"} singletonFactories:{} earlySingletonObjects:{} registeredSingletons:{"singleDog",...}
-
-
-
-
- singleDog 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
- blindman 走 addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)
-
结果
-
singletonFactories:{"blindman"} earlySingletonObjects:{} registeredSingletons:{"singleDog","blindman",...}
-
-
- blindman 走 populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)
- blindman 走 createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- blindman 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
-
blindman 走 afterSingletonCreation(String beanName)
-
结果
-
singletonsCurrentlyInCreation:{}
-
-
-
blindman 走 addSingleton(String beanName, Object singletonObject)
-
结果
-
singletonObjects:{"singleDog","blindman"} singletonFactories:{} earlySingletonObjects:{} registeredSingletons:{"singleDog","blindman",...}
-
-
-
-
测试数据
比较 @Autowired 注入和构造器注入
可以发现两者的区别体现在绿框框住的部分上。
<现象一>
@Autowired 注入会把识别到的 bean 都放到 singletonFactories 和 registeredSingletons 中;因为 blindman 依赖 singleDog,构造器注入会先把 blindman 依赖的 singleDog 放到 singletonFactories 和 registeredSingletons 中,等 singleDog 被放到 singletonObjects 时,blindman 才会被放到 singletonFactories 和 registeredSingletons 中,最终 blindman 也被放到了 singletonObjects。
复现依赖循环
不带构造器注入
前提
非构造器注入
@Component
public class Wife {
@Autowired
private Husband husband;
}
非构造器注入
@Component
public class Husband {
@Autowired
private Wife wife;
}
过程
doGetBeanNamesForType() 内 allowEarlyReference 为 false
- husband 走 getSingleton(String beanName, boolean allowEarlyReference)
-
判断
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
返回
-
null
-
-
- wife 走 getSingleton(String beanName, boolean allowEarlyReference)
-
判断
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
返回
-
null
-
-
doGetBean() 内 allowEarlyReference 为 true
- husband 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
-
husband 走 getSingleton(String beanName, boolean allowEarlyReference)
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
husband 走 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
-
判断
-
singletonObjects 无
-
-
husband 走 beforeSingletonCreation(String beanName)
-
singletonsCurrentlyInCreation:{"husband"}
-
-
husband 走 createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- husband 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- husband 走 createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- husband 走 addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)
-
结果
-
singletonFactories:{"husband"} earlySingletonObjects:{} registeredSingletons:{"husband"}
-
-
- husband 走 populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)
进入遍历执行 InstantiationAwareBeanPostProcessor 对象的 postProcessProperties() 方法
- wife 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
-
wife 走 getSingleton(String beanName, boolean allowEarlyReference)
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
wife 走 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
-
判断
-
singletonObjects 无
-
-
wife 走 beforeSingletonCreation(String beanName)
-
singletonsCurrentlyInCreation:{"wife","husband"}
-
-
wife 走 createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- wife 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- wife 走 createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- wife 走 addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)
-
结果
-
singletonFactories:{"husband","wife"} earlySingletonObjects:{} registeredSingletons:{"husband","wife"}
-
-
- wife 走 populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)
进入遍历执行 InstantiationAwareBeanPostProcessor 对象的 postProcessProperties() 方法
- husband 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
- husband 走 getSingleton(String beanName, boolean allowEarlyReference)
-
判断
-
singletonObjects 无 isSingletonCurrentlyInCreation true earlySingletonObjects 无 allowEarlyReference true singletonFactories 有
-
-
结果
-
earlySingletonObjects:{"husband"} singletonFactories:{"wife"}
-
-
返回
-
通过 singletonFactories 内获得的 bean
-
-
- husband 走 getSingleton(String beanName, boolean allowEarlyReference)
- husband 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
- wife 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
-
wife 走 afterSingletonCreation(String beanName)
-
结果
-
singletonsCurrentlyInCreation:{"husband"}
-
-
-
wife 走 addSingleton(String beanName, Object singletonObject)
-
结果
-
singletonObjects:{"wife",...} singletonFactories:{} earlySingletonObjects:{"husband"} registeredSingletons:{"husband","wife",...}
-
-
-
-
- wife 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
- husband 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
-
husband 走 afterSingletonCreation(String beanName)
-
结果
-
singletonsCurrentlyInCreation:{}
-
-
-
husband 走 addSingleton(String beanName, Object singletonObject)
-
结果
-
singletonObjects:{"wife","husband",...} singletonFactories:{} earlySingletonObjects:{} registeredSingletons:{"husband","wife",...}
-
-
-
-
测试数据
带构造器注入
前提
非构造器注入
@Component
public class Wife {
@Autowired
private Husband husband;
}
构造器注入
@Component
public class Husband {
private final Wife wife;
@Autowired
public Husband(Wife wife) {
this.wife = wife;
}
}
过程
doGetBeanNamesForType() 内 allowEarlyReference 为 false
- husband 走 getSingleton(String beanName, boolean allowEarlyReference)
-
判断
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
返回
-
null
-
-
- wife 走 getSingleton(String beanName, boolean allowEarlyReference)
-
判断
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
返回
-
null
-
-
doGetBean() 内 allowEarlyReference 为 true
- husband 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
-
husband 走 getSingleton(String beanName, boolean allowEarlyReference)
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
husband 走 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
-
判断
-
singletonObjects 无
-
-
husband 走 beforeSingletonCreation(String beanName)
-
singletonsCurrentlyInCreation:{"husband"}
-
-
husband 走 createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- husband 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- husband 走 createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- wife 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
-
wife 走 getSingleton(String beanName, boolean allowEarlyReference)
-
singletonObjects 无 isSingletonCurrentlyInCreation false
-
-
wife 走 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
-
判断
-
singletonObjects 无
-
-
wife 走 beforeSingletonCreation(String beanName)
-
singletonsCurrentlyInCreation:{"wife","husband"}
-
-
wife 走 createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- wife 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- wife 走 createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- wife 走 addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)
-
结果
-
singletonFactories:{"wife"} earlySingletonObjects:{} registeredSingletons:{"wife"}
-
-
- wife 走 populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)
- husband 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
- husband 走 getSingleton(String beanName, boolean allowEarlyReference)
-
判断
-
singletonObjects 无 isSingletonCurrentlyInCreation true earlySingletonObjects 无 allowEarlyReference true singletonFactories 无 -
返回
-
null
-
-
-
- husband 走 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
-
判断
-
singletonObjects 无 // 当前从创建检查中排除的 bean 的名称 inCreationCheckExclusions 无 // 当前正在创建的 bean 的名称 singletonsCurrentlyInCreation 有 - husband 走 beforeSingletonCreation(String beanName)
- beforeSingletonCreation() 抛出异常
-
-
- husband 走 getSingleton(String beanName, boolean allowEarlyReference)
- husband 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
- wife 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
-
-
- wife 走 doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
- husband 走 createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- husband 走 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
-
-
测试结果
比较不带构造器的依赖循环和 @Autowired 注入的正常流程
绿框内的部分为两者的区别。两者一开始都会把 bean 放到 singletonFactories 和 registeredSingletons 中,==当 不带构造器的依赖循环 检测到依赖循环时,husband 被放到了 earlySingletonObjects 中,然后等待 wife 处理完并被放到 singletonObjects 后才继续处理 husband==。
比较带构造器的依赖循环和带构造器的正常流程
两者在绿框之前的现象和 <现象一> 一致。到绿框部分时,带构造器的依赖循环 会把被依赖对象 singleDog 放进 singletonObjects 中,而 带构造器的正常流程 检测到依赖循环会卡死。
比较不带构造器和带构造器的依赖循环
在第一个绿框处的现象和 <现象一> 的绿框处一致。在第二个绿框处,不带构造器 会将 husband 从 singletonFactories 移动到 earlySingletonObjects 中,而 带构造器 则没有执行同样的步骤。
总结
带构造器的依赖循环之所以会报错是因为其不会把 bean 放进 earlySingletonObjects,导致 singletonObjects 一直为空
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!