循环依赖相关源码解析 - 图1
getBean是从容器中获取bean的入口方法,它里面又调用了doGetBean方法.

1.doGetBean从容器里面获取bean



这个方法里面有两个名称为getSingleton的方法,第一个getSingleton是从缓存中查找bean,如果缓存未命中,则走第二个getSingleton,尝试创建目标对象并注入依赖。当第一次调用doGetBean获取A对象,第一个getSingleton返回空,进入第二个getSingleton创建A对象,注入B对象。调用doGetBean获取B,第一个getSingleton返回空,进入第二个getSingleton创建B对象,获取并注入原始A对象,此时B对象初始化完成。最后将B对象注入A中,A完成初始化。

  1. protected T doGetBean(final String name, @Nullable final Class requiredType,
  2. @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  3. // 尝试通过bean名称获取目标bean对象,比如这里的A对象
  4. Object sharedInstance = getSingleton(beanName);
  5. // 我们这里的目标对象都是单例的
  6. if (mbd.isSingleton()) {
  7. // 这里就尝试创建目标对象,第二个参数传的就是一个ObjectFactory类型的对象,这里是使用Java8的lamada
  8. // 表达式书写的,只要上面的getSingleton()方法返回值为空,则会调用这里的getSingleton()方法来创建
  9. // 目标对象
  10. sharedInstance = getSingleton(beanName, () -> {
  11. try {
  12. // 尝试创建目标对象
  13. return createBean(beanName, mbd, args);
  14. } catch (BeansException ex) {
  15. throw ex;
  16. }
  17. });
  18. }
  19. return (T) bean;
  20. }

2.getSingleton(String beanName, boolean allowEarlyReference)检查缓存中是否已经存在实例化完毕的Bean


首先从一级缓存singletonObjects获取目标对象,若不存在且目标对象被标记为创建中,从二级缓存earlySingletonObjects中获取bean。如果不存在,继续访问三级缓存singletonFactories,得到bean工厂对象,通过工厂对象获取目标对象。将目标对象放入二级缓存,删除三级缓存。

该方法主要在AbstractBeanFactory的doGetBean方法调用。

  1. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  2. //首先检查一级缓存中是否存在
  3. Object singletonObject = this.singletonObjects.get(beanName);
  4. /**
  5. * 如果一级缓存中不存在代表当前 Bean 还未被创建或者正在创建中
  6. * 检查当前 Bean 是否正处于正在创建的状态中(当Bean创建时会将Bean名称存放到 singletonsCurrentlyInCreation 集合中)
  7. */
  8. if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  9. synchronized (this.singletonObjects) {
  10. //检查二级缓存中是否存在
  11. singletonObject = this.earlySingletonObjects.get(beanName);
  12. /**
  13. * @@如果二级缓存中不存在 并且 允许使用早期依赖
  14. * allowEarlyReference : 它的含义是是否允许早期依赖
  15. * @@那么什么是早期依赖?
  16. * 就是当Bean还未成为成熟的Bean时就提前使用它,在实例化流程图中我们看到在添加缓存前刚刚实例化Bean但是还未依赖注入时的状态
  17. */
  18. if (singletonObject == null && allowEarlyReference) {
  19. //获取三级缓存中的 Bean ObjectFactory
  20. ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
  21. //如果 Bean 对应的 ObjectFactory 存在
  22. if (singletonFactory != null) {
  23. //使用 getObject 方法获取到 Bean 的实例
  24. singletonObject = singletonFactory.getObject();
  25. //将 bean 从三级缓存提升至二级缓存
  26. this.earlySingletonObjects.put(beanName, singletonObject);
  27. //
  28. this.singletonFactories.remove(beanName);
  29. }
  30. }
  31. }
  32. }
  33. return singletonObject;
  34. }

3.getSingleton(String beanName, ObjectFactory<?> singletonFactory)

该方法的主要逻辑是调用singletonFactory的getObject()方法创建目标对象,然后将bean放入缓存中。

在创建主bean对象时,AbstractBeanFactory调用DefaultSingletonBeanRegistry的getSingleton方法:将主bean放入singletonsCurrentlyInCreation列表中,从而使得以上的三级缓存实现方法getSingleton,能够进入二三级缓存earlySingletonObjects,singletonFactories查找这个主bean,主要是给依赖bean查找主bean时使用的。

  1. public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
  2. synchronized (this.singletonObjects) {
  3. // ......
  4. // 将当前beanName放入singletonsCurrentlyInCreation中,以便解决循环依赖问题
  5. beforeSingletonCreation(beanName);
  6. // 调用 getObject 方法创建 bean 实例
  7. singletonObject = singletonFactory.getObject();
  8. newSingleton = true;
  9. if (newSingleton) {
  10. // 添加 bean 到 singletonObjects 缓存中,并从其他集合中将 bean 相关记录移除
  11. addSingleton(beanName, singletonObject);
  12. }
  13. // ......
  14. // 返回 singletonObject
  15. return (singletonObject != NULL_OBJECT ? singletonObject : null);
  16. }
  17. }
  18. protected void beforeSingletonCreation(String beanName) {
  19. if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
  20. throw new BeanCurrentlyInCreationException(beanName);
  21. }
  22. }

4.doCreateBean创建Bean

接着会调用AbstractAutowireCapableBeanFactory的createBean方法,而createBean方法会调用AbstractAutowireCapableBeanFactory的doCreateBean方法,doCreateBean的方法实现如下:先调用addSingletonFactory方法,在三级缓存singletonFactories中放入主bean的类型为ObjectFactory的singletonFactory对象创建工厂,这样在创建所依赖的bean对象时,可以通过三级缓存机制获取到主bean对象引用。

在doCreateBean方法中,调用populateBean进行属性赋值,其中步骤2的addSingletonFactory方法是在调用populateBean方法之前调用的,故在调用populateBean对主bean对象进行属性值注入或者setter注入时,主bean的创建工厂已经在singletonFactories缓存中了。

在populateBean方法中查找或者创建所依赖的bean对象。在创建所依赖的bean对象时,会调用到AbstractBeanFactory的doGetBean方法。而如果存在循环依赖,则所依赖的bean可以通过属性注入,setter方法注入,或者通过构造函数注入主bean:

如果通过属性值或者setter方法注入,则没有循环依赖问题。因为主bean和所依赖的bean都可以成功调用构造函数创建对象,通过对象引用来引用对方。属性值注入和setter方法注入,通过bean对象的后置处理器BeanPostProcessor来对该bean对象的属性值进行注入;
如果该依赖bean对象通过构造函数注入主bean对象,则在调用构造函数创建该依赖bean对象,需要查找主bean对象时,查找时会继续调用到AbstractBeanFactory的doGetBean方法获取主bean对象,而在AbstractBeanFactory的doGetBean方法调用getSingleton方法检查三级缓存是否可以得到主bean对象。由步骤1和步骤2可知,由于getSingleton方法的singletonsCurrentlyInCreation和singletonFactories都已经有了主bean的相关信息,通过三级缓存可以查找到主bean对象,即通过主bean对象的创建工厂singletonFactories创建提前曝光的主bean对象,并放入二级缓存arlySingletonObjects,故可以解决为这个依赖bean对主bean的依赖注入,从而成功创建该依赖对象bean。
当创建好这个依赖bean对象之后,主bean的属性可以完整注入成功。而由于该所依赖bean包含了主bean中对象引用,故该所依赖的bean对象可以访问和使用主bean,该所依赖的bean对象也是完整的对象,从而最终解决了主bean和所依赖bean之间的循环依赖问题。


1. 用createBeanInstance创建目标对象
2. 将对象添加到singletonFactories缓存中
3. populateBean注入依赖

  1. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
  2. throws BeanCreationException {
  3. /**
  4. * 我们一开始通过 getSingleton() 方法中获取三级缓存中存放的Bean,这里就是向三级缓存中添加 bean 的地方
  5. * 流程:
  6. * 1.检查当前 bean 是否为单例模式,并且是否允许循环引用[讲解1],并且当前是否正在创建中(在getSingleton方法中添加的)
  7. * 2.如果允许提前曝光[讲解2],addSingletonFactory() 方法向缓存中添加当前 bean 的 ObjectFactory
  8. *
  9. * [讲解1]:当前 Bean 如果不允许循环引用(循环依赖也就是被依赖),则这里就不会提前曝光,对应的 ObjectFactory
  10. * 则当发生循环依赖时会抛出 BeanCreationException 异常
  11. *
  12. * [讲解2]:提前曝光的含义就是说当 bean 还未创建完毕时就先将创建中状态的bean放到指定缓存中,为循环依赖提供支持
  13. */
  14. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  15. isSingletonCurrentlyInCreation(beanName));
  16. //需要提前曝光
  17. if (earlySingletonExposure) {
  18. /**
  19. * 向缓存(三级缓存)中添加当前 bean 的 ObjectFactory
  20. */
  21. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  22. }
  23. /**
  24. * Initialize the bean instance.
  25. * 初始化 Bean 实例阶段
  26. */
  27. Object exposedObject = bean;
  28. try {
  29. /**
  30. * 依赖注入这时会递归调用getBean
  31. */
  32. populateBean(beanName, mbd, instanceWrapper);
  33. //调用初始化方法,如:init-method
  34. exposedObject = initializeBean(beanName, exposedObject, mbd);
  35. }
  36. /**
  37. * 当允许提前曝光时进入判断
  38. * @这里做了什么?
  39. * 1.检查当前bean是否经历了一场循环依赖
  40. * - 通过 getSingleton(beanName,false) 获取缓存中的 bean,传入 false 代表不获取三级缓存中的bean
  41. * - 为什么说 检查当前bean是否经历了一场循环依赖呢? 因为上述说了传入 false 代表不获取三级缓存的
  42. * - 那么什么情况下才会存在与一级缓存和二级缓存呢?答案就是循环依赖后 [解释1] 和bean实例化完成后
  43. * - 所以如果 getSingleton 返回的 bean 不为空,则这个bean就是刚刚经历了循环依赖
  44. *
  45. * 2.检查提前曝光的bean和当前的Bean是否一致
  46. * - 下面有个判断 if (exposedObject == bean) ,这个判断从缓存中获取的bean 和 经历过初始化后的 bean
  47. * - 是否一致,可能我们有点晕,这里解释一下,缓存从的bean是什么时候存进去的?是在 addSingletonFactory 方法(649行)
  48. * - 然后这里存进去的 bean 只是提前曝光的 bean,还没有依赖注入和初始化,但是在依赖注入和初始化时都是可能直接改变
  49. * - 当前 bean 的实例的,这意味着什么?意味着经历了依赖注入和初始化的bean很可能和缓存中的bean就已经完全不是一个 bean了
  50. * 下面讲解当一致或不一致时的逻辑:
  51. * 2.1 一致:
  52. * 不是很理解,直接赋值,可是经历了各种 BeanPostProsser 或者依赖注入和初始化后不是就不一样了吗
  53. * 2.2 不一致:
  54. * 看下方对于 else if 代码块的解释
  55. *
  56. * @[解释1]
  57. * 当循环依赖时,A依赖着B,B依赖着A,实例化A首先将A放到三级缓存中然后发现依赖着B,然后去实例化B,发现依赖着A
  58. * 发现A在三级缓存,然后获取三级缓存中的bean并且将A从三级缓存中提升到二级缓存中,实例化B完成,接着实例化A也完成。
  59. *
  60. * @通俗讲解
  61. * 假设我们业务上对某种数据加了缓存,假设 i 在缓存中存的值为1,当我在数据库中把 i 的值改成 2 时,缓存中的 i 还没有被改变还是 1
  62. * 这时的数据已经和我们的真实数据偏离了,不一致了,这时有两种解决方式:1.服务器检查到数据不一致抛出异常。(也就是进入else if 代码块)
  63. * 2.直接使用原始值也就是1(也就是将 allowRawInjectionDespiteWrapping 改成 true),当然这两种方式明显不是我们正常数据库的操作,只是
  64. * 为了说明当前的这个例子而已。
  65. *
  66. */
  67. if (earlySingletonExposure) {
  68. //获取缓存中(除三级缓存) beanName 对应的 bean
  69. Object earlySingletonReference = getSingleton(beanName, false);
  70. //当经历了一场循环依赖后 earlySingletonReference 就不会为空
  71. if (earlySingletonReference != null) {
  72. //如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
  73. if (exposedObject == bean) {
  74. //直接赋值? 可是经历了各种 BeanPostProsser 或者依赖注入和初始化后不是就不一样了吗
  75. exposedObject = earlySingletonReference;
  76. }
  77. /**
  78. *
  79. * 走到 else if 时说明 当前 Bean 被 BeanPostProessor 增强了
  80. * 判断的条件为:
  81. * 1.如果允许使用被增强的
  82. * 2.检查是否存在依赖当前bean的bean
  83. *
  84. * 如果存在依赖的bean已经被实例化完成的,如果存在则抛出异常
  85. * 为什么抛出异常呢?
  86. * 因为依赖当前bean 的bean 已经在内部注入了当前bean的旧版本,但是通过初始化方法后这个bean的版本已经变成新的了
  87. * 旧的哪个已经不适用了,所以抛出异常
  88. *
  89. */
  90. else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
  91. String[] dependentBeans = getDependentBeans(beanName);
  92. Set actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
  93. for (String dependentBean : dependentBeans) {
  94. if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
  95. actualDependentBeans.add(dependentBean);
  96. }
  97. }
  98. if (!actualDependentBeans.isEmpty()) {
  99. throw new BeanCurrentlyInCreationException(beanName,
  100. "Bean with name '" + beanName + "' has been injected into other beans [" +
  101. StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
  102. "] in its raw version as part of a circular reference, but has eventually been " +
  103. "wrapped. This means that said other beans do not use the final version of the " +
  104. "bean. This is often the result of over-eager type matching - consider using " +
  105. "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
  106. }
  107. }
  108. }
  109. }
  110. try {
  111. /**
  112. * Register bean as disposable.
  113. * 注册 Bean 的销毁方法拓展
  114. */
  115. registerDisposableBeanIfNecessary(beanName, bean, mbd);
  116. }
  117. catch (BeanDefinitionValidationException ex) {
  118. throw new BeanCreationException(
  119. mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
  120. }
  121. return exposedObject;
  122. }




最后,注入成功之后,都会将单例bean对象放入一级缓存singletonObjects中,并移除存放提前曝光对象的二级缓存earlySingletonObjects和该bean对象的创建工厂缓存earlySingletonObjects,如下为DefaultSingletonBeanRegistry的getSingleton方法实现和addSingleton方法实现:

  1. public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
  2. // 省略其他代码
  3. // 将当前beanName放入singletonsCurrentlyInCreation中,以便解决循环依赖问题
  4. beforeSingletonCreation(beanName);
  5. try {
  6. // getObject方法会调用AbstractAutowireCapableBeanFactory的createBean方法
  7. singletonObject = singletonFactory.getObject();
  8. newSingleton = true;
  9. }
  10. // 省略其他代码
  11. if (newSingleton) {
  12. // 创建好bean对象后,放入singleObjects缓存中
  13. addSingleton(beanName, singletonObject);
  14. }
  15. return singletonObject;
  16. }
  17. }
  18. protected void addSingleton(String beanName, Object singletonObject) {
  19. synchronized (this.singletonObjects) {
  20. // 放入一级缓存
  21. this.singletonObjects.put(beanName, singletonObject);
  22. // 移除二三级缓存
  23. this.singletonFactories.remove(beanName);
  24. this.earlySingletonObjects.remove(beanName);
  25. this.registeredSingletons.add(beanName);
  26. }
  27. }