在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的一个部分初始化实例。
解决循环依赖的流程
- 当A依赖于B,B又依赖于A时,Spring在创建A的过程中,将A的Factory对象放入
singletonFactories
。 - 当B创建时,尝试从
singletonObjects
获取A,由于A尚未完全初始化,所以获取不到,然后从earlySingletonObjects
和singletonFactories
中查找。 - 从
singletonFactories
中找到A的Factory对象,通过它创建A的部分初始化实例,并将这个实例放入earlySingletonObjects
。 - B现在可以使用A的部分初始化实例继续其自身的初始化过程。
- 同样的逻辑应用于A对B的依赖。
- 当A和B都完成了初始化后,它们会被移出
earlySingletonObjects
,放入singletonObjects
,供后续的依赖注入使用。
通过这种方式,Spring能够优雅地处理循环依赖,确保Bean的正常创建和初始化。