下面是对"Spring源码之循环依赖之三级缓存详解"的完整攻略:
什么是循环依赖
循环依赖指的是对象之间出现相互依赖的情况,通常是两个或多个对象互相持有对方的引用,从而导致它们之间出现循环依赖的问题。在Spring框架中,循环依赖的问题通常在bean的创建过程中出现。
三级缓存解决循环依赖问题
Spring框架为了解决bean之间的循环依赖问题,设计了三级缓存机制,其中包含singletonObjects、earlySingletonObjects和singletonFactories三个缓存:
- singletonObjects缓存是最终保存已经构造完成的bean的缓存,用于存储所有的单例bean实例。
- earlySingletonObjects缓存是正在创建或已经创建完成但是没有完成其他bean之间注入的bean的缓存,它保存的是还未完全创建完成的实例,即在bean实例化过程中就已经被加入earlySingletonObjects缓存中,它们是被Spring容器创建过的但是还未完全实例化完毕,不能被其他的bean注入。
- singletonFactories缓存是用于存储创建中的bean工厂的,它主要保存的是一些提供beanObjectFactory方便其他bean属性注入、实例化时需要的函数来创建bean的缓存对象。
这三个缓存之间共同协作,优先依次检查earlySingletonObjects、singletonFactories和singletonObjects三个缓存,建立和获取bean,直到最终创建完成。
Spring循环依赖解决机制的详细过程
当我们向Spring容器中添加一个bean时,Spring容器会首先检查singletonObjects缓存是否存在该bean,若存在,则直接返回缓存中的bean,否则,则继续检查earlySingletonObjects缓存是否存在该bean。
若earlySingletonObjects缓存中没有该bean,则继续检查singletonFactories缓存是否存在该bean。若存在,则依据singletonFactories实例化并初始化bean,并将新的bean实例放到earlySingletonObjects缓存中。
若earlySingletonObjects缓存中存在该bean,则说明当前bean正在创建过程中且已经存在循环依赖,那么将会返回早期的bean实例,并根据链表追加属性。
若singletonFactories缓存中没有该bean,则说明bean还没有被创建。此时Spring会继续实例化并初始化该bean,并将生成的bean实例放到earlySingletonObjects缓存中,同时生成该bean对应的beanFactory方法工厂。在初始化期间,生成bean的属性时会走子属性,如果子属性是一个已经创建完成的单例实例,那么就会使用singletonObjects中的实例。最后,Spring会将生成的bean实例放到singletonObjects缓存中,从而成功解决了循环依赖的问题。
示例说明
为了更好地理解Spring的三级缓存机制,假设我们有两个依赖关系为b -> a,即b依赖于a的bean。 模拟过程如下:
- Spring容器从singletonObjects缓存中查找b的实例。因为它还没有创建,因此singletonObjects缓存没有查找到b的实例。
- Spring容器继续从earlySingletonObjects查找b的实例。earlySingletonObjects缓存中没有b实例。
- Spring容器从singletonFactories查找b的beanFactory。找到了对应的beanFactory,使用beanFactory创建b实例,并将b的实例放入到earlySingletonObjects缓存中。
- Spring容器创建a实例时,需要使用b实例作为依赖注入的属性,而此时b的实例还没有完全初始化,因此Spring容器会返回一个b的代理对象。
- Spring容器继续创建b实例,发现b依赖于a的bean,因此需要从singletonObjects中获取a的实例。
- 但是此时a的实例还没有完全初始化,因此Spring容器会返回a的代理对象。
- Spring容器继续初始化a实例,并将最终的a实例放入到singletonObjects缓存中。
- Spring容器接着初始化b实例,将最终的b实例放入到singletonObjects缓存中并完成b实例化。
在这个示例中,a实例是首先被初始化的,而b实例是在a完成初始化后才被初始化的,通过三级缓存机制确保了b的代理对象能够顺利地依赖于a。这就是Spring框架解决循环依赖的机制。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring源码之循环依赖之三级缓存详解 - Python技术站