spring三级缓存解决循环依赖原理

在Spring框架中,Bean的实例化和管理是通过其核心的IoC容器完成的。在处理Bean的依赖注入时,可能会遇到循环依赖的问题,即两个或多个Bean相互引用对方。为了解决这一问题,Spring采用了三级缓存机制。

一级缓存:singletonObjects

这是Spring IoC容器中的主要缓存,用于存放已经创建并完全初始化完毕的单例Bean。当一个Bean被请求时,Spring会首先从这个缓存中查找是否存在,如果存在则直接返回,避免了重复创建。

二级缓存:earlySingletonObjects

这是一个临时缓存,在Bean的创建过程中使用。当Bean的构造函数执行完毕,但尚未进行属性填充和初始化方法调用时,Bean会被暂时放入这个缓存中。这样,如果在这个阶段有其他Bean请求依赖于它,可以从这里获取到部分初始化的Bean实例,从而避免了循环依赖导致的异常。

三级缓存:singletonFactories

这是一个工厂缓存,存储的是Bean的Factory对象。当一个Bean正在被创建但还未完全初始化时,它的Factory对象会被放入这个缓存中。如果此时有其他Bean请求依赖于它,Spring会从这个缓存中获取Factory对象,并通过它来获取当前正在创建的Bean的一个部分初始化实例。

解决循环依赖的流程

  1. 当A依赖于B,B又依赖于A时,Spring在创建A的过程中,将A的Factory对象放入singletonFactories
  2. 当B创建时,尝试从singletonObjects获取A,由于A尚未完全初始化,所以获取不到,然后从earlySingletonObjectssingletonFactories中查找。
  3. singletonFactories中找到A的Factory对象,通过它创建A的部分初始化实例,并将这个实例放入earlySingletonObjects
  4. B现在可以使用A的部分初始化实例继续其自身的初始化过程。
  5. 同样的逻辑应用于A对B的依赖。
  6. 当A和B都完成了初始化后,它们会被移出earlySingletonObjects,放入singletonObjects,供后续的依赖注入使用。

按照以下步骤来描述这一过程:

  1. 开始创建Bean A:

    • 检查singletonObjects缓存中是否已有Bean A的实例。
    • 如果没有,开始实例化Bean A,并将Bean A的工厂对象放入singletonFactories缓存。
  2. 实例化Bean A:

    • 调用Bean A的构造器,创建Bean A的实例,但不填充依赖。
    • 将创建的Bean A实例(部分初始化状态)放入earlySingletonObjects缓存。
    • 标记Bean A为正在创建中。
  3. 解析Bean A的依赖:

    • 当解析到Bean A依赖Bean B时,尝试从singletonObjects获取Bean B。
    • 如果Bean B尚未创建,进入Bean B的创建流程。
  4. 开始创建Bean B:

    • 检查singletonObjects缓存中是否已有Bean B的实例。
    • 如果没有,开始实例化Bean B,并将Bean B的工厂对象放入singletonFactories缓存。
  5. 实例化Bean B:

    • 调用Bean B的构造器,创建Bean B的实例,但不填充依赖。
    • 将创建的Bean B实例(部分初始化状态)放入earlySingletonObjects缓存。
    • 标记Bean B为正在创建中。
  6. 解析Bean B的依赖:

    • 当解析到Bean B依赖Bean A时,不从singletonObjects获取,而是从earlySingletonObjects获取Bean A的早期引用。
  7. 继续创建Bean B:

    • 使用从earlySingletonObjects中获取的Bean A的早期引用,完成Bean B的依赖填充。
    • 完成Bean B的初始化,包括调用初始化方法等。
    • 将完全初始化的Bean B放入singletonObjects缓存,并从earlySingletonObjectssingletonFactories中移除Bean B的条目。
  8. 继续创建Bean A:

    • 使用从earlySingletonObjects中获取的Bean B的早期引用,完成Bean A的依赖填充。
    • 完成Bean A的初始化,包括调用初始化方法等。
    • 将完全初始化的Bean A放入singletonObjects缓存,并从earlySingletonObjectssingletonFactories中移除Bean A的条目。
  9. 结束:

    • 此时,Bean A和Bean B都已经完全初始化,并存储在singletonObjects中,可以供其他Bean依赖使用。

通过这种方式,Spring能够优雅地处理循环依赖,确保Bean的正常创建和初始化。

posted @ 2024-07-08 16:03  使用D  阅读(24)  评论(0编辑  收藏  举报