Spring解决循环引用

发布时间 2024-01-03 09:41:32作者: zzusjw

跟着孙哥学Spring,b站:https://www.bilibili.com/video/BV185411477k/?spm_id_from=333.337.search-card.all.click

要理解Spring是如何解决循环引用的,首先需要掌握Spring的三个关键Map对象:

● singletonObjects:线程安全,存储完全初始化的单例Bean。
● earlySingletonObjects:存储已被实例化但未完全初始化的单例Bean,未进行属性填充和初始化。
● singletonFactories:存储创建单例Bean的ObjectFactory。

对象创建的三个主要步骤

Spring创建对象经历以下三个阶段:

● 实例化对象
● 属性填充
● 初始化

在实例化BeanA后,Spring会将创建单例BeanA的ObjectFactory存入singletonFactories。
image

属性填充阶段

在填充BeanA的属性时,如果发现某个属性引用了BeanB,Spring会尝试从缓存中获取BeanB。当从缓存中获取不到BeanB时,会走创建bean对象的流程。

当BeanB的属性填充遇到BeanA时,Spring会从singletonFactories获取相应的ObjectFactory,并通过回调其方法来实际创建BeanA的完整实例。
1. 从singleFactories中,获取创建beanA的工厂对象,利用函数式接口回调,创建“不完整”的对象BeanA。
2. 将“不完整”的对象BeanA存入earlySingleObjects,此时BeanA尚未进行属性填充和初始化。
3. 接口回调后,Spring会将BeanA放入earlySingletonObjects,表示该BeanA已被创建但尚未完全初始化。接着,Spring会从singletonFactories中移除对应的ObjectFactory。
image

走完protected Object getSingleton(String beanName, boolean allowEarlyReference)这个方法,返回了“不完整”的BeanA,对象B属性填充阶段和初始化阶段,接着按流程走完。
image

对象B已经是一个完整的对象了。

此时需要进行三个Map的维护:
image
addSingleton(beanName, singletonObject)方法详情:
image
将对象BeanB存入singletonObject中,并从earlySingletonObjects中将“不完整”的BeanB移除。

接着,对象BeanA进行属性填充和初始化流程。

至此,Spring已经解决了循环引用问题。

孙哥的随堂笔记
image