概述

Bean 的加载涉及到 获取 Bean 定义,实例化、属性填充、初始化过程。
在初始化阶段 ,Spring 对 Aware、BeanPostProcessor 等扩展点进行了实现,对 Bean 进行增强。
在初始化阶段,有将 Bean 放到三级缓存,然后到二级缓存,最后初始化完成放到一级缓存的过程,具体可以看看上篇文章。
Spring Bean 加载过程生命周期源码分析
注意:

  • Spring 只解决了单例 Bean 循环依赖的情况
  • 依赖注入的方式不能全是构造器注入

    样例代码

    样例代码只包含 3 个类,启动类 SpringBeanCircleApplication ,CircularServiceA 依赖 CircularServiceB,CircularServiceB 依赖 CircularServiceA 。 ```java @SpringBootApplication public class SpringBeanCircleApplication {

    public static void main(String[] args) {

    1. SpringApplication.run(SpringBeanCircleApplication.class, args);

    } }

@Service public class CircularServiceA {

  1. @Autowired
  2. private CircularServiceB circularServiceB;

}

@Service public class CircularServiceB {

  1. @Autowired
  2. private CircularServiceA circularServiceA;

}

  1. <a name="kw9qy"></a>
  2. # 源码分析
  3. 循环依赖的 Bean 加载流程:
  4. 1. A 的**加载流程**包括**实例化、属性填充、初始化**三个阶段。A 实例化完成之后,会将 Bean 标记为**创建中**(还未属性填充、初始化)、并且实例的 objectFactory 加入到三级缓存。其中在 A **属性填充**阶段,发现 B 还未加载,进而去执行 B 的加载流程
  5. 1. B 的加载流程和 A 一样,B 实例化完成后,会将 B 标记为创建中、加入到三级缓存。此时三级缓存中有 A、B 的 ObjectFactory。
  6. 1. 在 B **属性填充**阶段,又发现 A ,进而**又去加载 A** 。加载 A 发现其正在**创建中**,并且三级缓存中有 A,那么将 A 放到二级缓存,并返回 A 的引用。
  7. 1. 至此 B 属性填充完成,再执行 B 初始化,初始化完成后将 B 从三级移动到二级再移动到一级缓存中。
  8. 1. 再执行 A 属性填充后的初始化流程,并放到一级缓存。最终,一级缓存里面包含 A 和 B 初始化完成的实例
  9. 沿用网上一张图片:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/210984/1653355734935-d0ffb50d-9851-4774-b6ad-38598e13dfbc.png#clientId=ue0214836-b5ff-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u811a7ea2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=972&originWidth=1257&originalType=url&ratio=1&rotation=0&showTitle=false&size=143634&status=done&style=none&taskId=ufd1cbcc5-dc7a-4ab5-af6d-eef2d44f213&title=)
  10. <a name="bKUGI"></a>
  11. ## 1. getBean(A)
  12. A 的加载流程
  13. <a name="vIF5O"></a>
  14. ### 1.1 AbstractBeanFactory
  15. - 从 getBean 开始,首先从缓存中获取(**这个步骤很重要**)
  16. - 若缓存中没有,再获取 A 的定义,其次调用 getSingleton 去获取 A 的实例,createBean 方法用于创建 A 的 objectFactory。
  17. - 若缓存中有,直接返回实例
  18. ```java
  19. public abstract class AbstractBeanFactory {
  20. public Object getBean(String name) throws BeansException {
  21. return this.doGetBean(name, (Class)null, (Object[])null, false);
  22. }
  23. protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
  24. Object sharedInstance = this.getSingleton(beanName); // 从缓存中获取 A,第一次显然获取不到
  25. try {
  26. RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName); // 获取 Bean 定义
  27. if (mbd.isSingleton()) {
  28. // 获取 A 的实例
  29. sharedInstance = this.getSingleton(beanName, () -> {
  30. try {
  31. return this.createBean(beanName, mbd, args); // 执行 singletonFactory.getObject 会被调用
  32. } catch (BeansException var5) {
  33. this.destroySingleton(beanName);
  34. throw var5;
  35. }
  36. });
  37. beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  38. }
  39. }
  40. }
  41. }

1.2 DefaultSingletonBeanRegistry

  • getSingleton(String beanName, ObjectFactory<?> singletonFactory) 执行到 singletonFactory.getObject 这一行时,会调用函数调用的地方 Lamda 表达式的 AbstractAutowireCapableBeanFactory.createBean 方法
  • getSingleton 方法结束部分,表示 Bean 已经初始化完成,此时移除 Bean 创建中标记,并加入到一级缓存中

    1. public class DefaultSingletonBeanRegistry {
    2. public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    3. synchronized(this.singletonObjects) {
    4. Object singletonObject = this.singletonObjects.get(beanName); // 再次从缓存中获取 A,显然获取不到
    5. if (singletonObject == null) {
    6. this.beforeSingletonCreation(beanName); // 标记创建中,加入到 singletonsCurrentlyInCreation
    7. try {
    8. singletonObject = singletonFactory.getObject(); // 执行 lamda 表达式,AbstractAutowireCapableBeanFactory.createBean 返回 实例
    9. newSingleton = true;
    10. } finally {
    11. // A 加载结束,移除正在创建标记 singletonsCurrentlyInCreation
    12. this.afterSingletonCreation(beanName);
    13. }
    14. if (newSingleton) {
    15. // 添加到一级缓存,删除二级缓存与一级缓存
    16. this.addSingleton(beanName, singletonObject);
    17. }
    18. }
    19. }
    20. }
    21. }

    1.3 AbstractAutowireCapableBeanFactory

    执行具体 Lamda 表达式的内容,注意属性填充前,将对象加入的三级缓存的部分,后面会说到三级缓存的作用 ```java public abstract class AbstractAutowireCapableBeanFactory { protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

    1. beanInstance = this.doCreateBean(beanName, mbdToUse, args);

    }

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

    1. if (instanceWrapper == null) {
    2. instanceWrapper = this.createBeanInstance(beanName, mbd, args); // A 实例化
    3. }
    4. // 是否单例 && 运行循环依赖 && 创建中
    5. boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
    6. if (earlySingletonExposure) {
    7. // 将对象放到三级缓存
    8. this.addSingletonFactory(beanName, () -> {
    9. return this.getEarlyBeanReference(beanName, mbd, bean);
    10. });
    11. }
    12. try {
    13. this.populateBean(beanName, mbd, instanceWrapper); // 属性填充(此时发现 A )
    14. exposedObject = this.initializeBean(beanName, exposedObject, mbd); // 初始化
    15. }
    16. if (earlySingletonExposure) {
    17. // 只从一级缓存和二级缓存中取
    18. Object earlySingletonReference = this.getSingleton(beanName, false);
    19. if (earlySingletonReference != null) {
    20. if (exposedObject == bean) {
    21. exposedObject = earlySingletonReference;
    22. }
    23. }
    24. }

    } }

// 属性填充 protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) { MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs); if (resolvedAutowireMode == 1) { this.autowireByName(beanName, mbd, bw, newPvs); }

  1. if (resolvedAutowireMode == 2) {
  2. this.autowireByType(beanName, mbd, bw, newPvs);
  3. }
  4. pvs = newPvs;
  5. }

}

protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { for(int var8 = 0; var8 < var7; ++var8) { String propertyName = var6[var8]; if (this.containsBean(propertyName)) { // 如果含有 Bean,那么执行 Bean 加载逻辑 Object bean = this.getBean(propertyName); // A 发现 B,那么执行 B 的加载流程 } }

}

  1. **可以发现,在 A populateBean 阶段,会去调用 getBean(B) 的逻辑**
  2. <a name="D7agh"></a>
  3. ## 2. getBean(B)
  4. B 的加载流程,其加载流程和 A 一样(1.11.21.3 部分)<br />**重点来了,在 B populateBean 阶段,又发现了 A,此时再去执行 getBean(A)**
  5. <a name="umAd1"></a>
  6. ## 3. getBean(A)
  7. A 再次被加载<br />AbstractBeanFactory.getBean 方法开头,发现此时**三级缓存**中有 A ObjectFactory,并且标记为创建中,那么把 A ObjectFactory **从三级缓存**(singletonFactories)**放到二级缓存**(earlySingletonObjects)中,并返回 A 的提前曝光实例(还未初始化完成)
  8. ```java
  9. public abstract class AbstractBeanFactory {
  10. protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
  11. Object sharedInstance = this.getSingleton(beanName);
  12. if (sharedInstance != null && args == null) {
  13. beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
  14. }
  15. }
  16. public class DefaultSingletonBeanRegistry{
  17. @Nullable
  18. public Object getSingleton(String beanName) {
  19. return this.getSingleton(beanName, true);
  20. }
  21. // 从缓存获取逻辑
  22. @Nullable
  23. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  24. Object singletonObject = this.singletonObjects.get(beanName); // 从一级缓存获取
  25. if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) { // 没有获取到并且正在创建中
  26. singletonObject = this.earlySingletonObjects.get(beanName); // 从二级缓存获取
  27. if (singletonObject == null && allowEarlyReference) { // 二级缓存也没有获取到,并且允许提前返回引用
  28. synchronized(this.singletonObjects) { // 加锁
  29. singletonObject = this.singletonObjects.get(beanName); // 再次从一级缓存获取
  30. if (singletonObject == null) { // 一级没有
  31. singletonObject = this.earlySingletonObjects.get(beanName); // 二级中获取
  32. if (singletonObject == null) { // 二级也没有
  33. ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName); // 从三级获取
  34. if (singletonFactory != null) {
  35. singletonObject = singletonFactory.getObject();
  36. this.earlySingletonObjects.put(beanName, singletonObject); // 从三级中获取到了,删除三级缓存,加入到二级缓存中
  37. this.singletonFactories.remove(beanName);
  38. }
  39. }
  40. }
  41. }
  42. }
  43. }
  44. return singletonObject;
  45. }
  46. }

4. B 初始化完成

上一步 B 属性填充完成之后,执行 AbstractAutowireCapableBeanFactory 中后续的初始化流程、并在 DefaultSingletonBeanRegistry.getSingleton 方法最后,移除 Bean 创建中标记,将缓存从三级移到一级。

5. A 初始化完成

与上面步骤一样

为什么需要三级缓存

根据上面流程可知,A、B 的加载,首先都会放到三级缓存中,当再次调用 getBean(A) 方法时,从三级缓存中通过 ObjectFactory.getObject 获取 A 的实例。
若 A 被 AOP 代理,那么执行匿名表达式的exposedObject = bp.getEarlyBeanReference(exposedObject, beanName)操作,返回的是 A 的代理对象
image.png
可以用反证法证明三级缓存的必要性:

  • 若只有两级缓存,创建 A 实例时,不知道是否有循环依赖,先将 A 放到二级缓存;创建 B 实例时,也放入二级缓存。
  • B 属性填充阶段发现了 A,进从二级缓存中找到了 A,若 A 被 AOP 代理,此时从二级缓存中获取的 A 是原始对象并不是代理对象,不符合要求。
  • 若一开始将 A 的代理对象放入二级缓存,这样违背了 Spring AOP 与 Bean 的生命周期的设计,因为在没有循环依赖的常规情况下,AOP 的实现都是 Bean 初始化完成之后才进行。
  • 所以若出现了循环依赖,三级缓存就很有必要,把实例对象的 ObjectFactory 放到三级缓存中,通过 singletonFactory.getObject() 方法判断是否需要返回 A 的代理类,对 A 提前做增强。

    1. public abstract class AbstractAutowireCapableBeanFactory {
    2. protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    3. // 是否单例 && 运行循环依赖 && 创建中
    4. boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
    5. if (earlySingletonExposure) {
    6. // 将对象放到三级缓存
    7. this.addSingletonFactory(beanName, () -> {
    8. return this.getEarlyBeanReference(beanName, mbd, bean);
    9. });
    10. }
    11. }
    12. protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    13. Object exposedObject = bean;
    14. SmartInstantiationAwareBeanPostProcessor bp;
    15. // 有代理
    16. if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
    17. // for 循环参数结尾,返回实例的提前曝光对象
    18. for(Iterator var5 = this.getBeanPostProcessorCache().smartInstantiationAware.iterator(); var5.hasNext(); exposedObject = bp.getEarlyBeanReference(exposedObject, beanName)) {
    19. bp = (SmartInstantiationAwareBeanPostProcessor)var5.next();
    20. }
    21. }
    22. // 返回可能被代理的对象
    23. return exposedObject;
    24. }
    25. }

    循环依赖情况

    | 依赖情况 | 依赖注入方式 | 循环依赖是否被解决 | | —- | —- | —- | | AB相互依赖(循环依赖) | 均采用 setter 方法注入 | 是 | | AB相互依赖(循环依赖) | A中注入B的方式为setter方法 | 是 | | AB相互依赖(循环依赖) | B中注入A的方式为 setter 方法,A中注入B的方式为构造器 | 否 | | AB相互依赖(循环依赖) | B中注入A的方式为setter方法,A中注入B的方式为构造器 | 是(可以使用 @Lazy 解决) |

  1. Spring 创建 Bean 是按照自然排序,若主 Bean 是 setter 方式,那么依赖 Bean 是 setter 注入或者构造器注入,都可以解决循环依赖问题
  2. 均使用构造器注入,可以使用 @Lazy 解决,其基本思路是:对于强依赖的对象,一开始并不注入对象本身,而是注入其代理对象 ```java @Service public class CircularServiceA { private CircularServiceB circularServiceB; public CircularServiceA(@Lazy CircularServiceB circularServiceB){
    1. this.circularServiceB = circularServiceB;
    } }

@Service public class CircularServiceB { private CircularServiceA circularServiceA; public CircularServiceB(CircularServiceA circularServiceA){ this.circularServiceA = circularServiceA; } } ```

参考

面试必杀技,讲一讲Spring中的循环依赖
Spring 循环依赖及解决方式