singletonObjects: 用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
earlySingletonObjects: 存放早期曝光的 bean 对象(尚未填充属性),用于解决循环依赖
singletonFactories: 存放 bean 工厂对象,用于解决循环依赖
在容器再次发现 beanB 依赖于 beanA 时,容器会获取 beanA 对象的一个早期的引用(early reference),并把这个早期引用注入到 beanB 中,让 beanB 先完成实例化.beanB 完成实例化,beanA 就可以获取到 beanB 的引用,beanA 随之完成实例化
创建 a 对象时
1.尝试从 singletonObject 缓存中获取 bean,获取不到 并且 且 当前 bean 没有处于正在创建中,返回 null.
2.singleton bean a 的创建
2.1.先尝试从 singletonObjects 中获取
2.2.若上面获取不到
2.2.1.向 singletonsCurrentlyInCreation 缓存中记录 beanName,表示 a 正在创建中
2.2.2.使用传入的 singletonFactory 创建 bean
2.2.2.1.createBean() 中 根据不同的实例化策略实例化 bean,如 工厂方法 或 构造器.实例化后包装成 BeanWrapper.
2.2.3.判断是否需要提早暴露: 单例 且 允许循环依赖 且 当前bean正在创建中,则需要提前暴露,用于解决循环依赖
2.2.3.1.若需要早期曝光.则将 singletonFactory 添加到 singletonFactories 中,并从 earlySingletonObjects 中移除缓存.这里传入的 singletonFactory 的 getObject() 方法 返回的是 getEarlyBeanReference,即早期引用的 bean.
2.2.4.populateBean() 对 bean 进行属性装配.其中可能存在依赖于其他 bean 的属性,则会递归初始化.
创建 b 对象时,流程和上面类似.
当 b 调用 populateBean() 装配依赖的 a 时,流程如下:
1.从 beanFactory 中获取 a
1.1.尝试从 singletonObject 缓存中获取 bean
1.2.由于上面获取不到,且 a 当前正在创建中,则尝试从 earlySingletonObjects(早期曝光)缓存中获取 a
1.3.由于 earlySingletonObjects 中也获取不到a,且允许早期曝光(earlyReference),则从 singletonFactories 中获取 singletonFactory
1.4.通过 singletonFactory.getObject() 返回早期曝光的 bean,这个 bean a 还未完成 populateBean() 属性装配
1.5.创建完早期曝光 bean 后,添加到 earlySingletonObjects 缓存中,下次直接从这个缓存中取 早期曝光的 bean 了.并且从 singletonFactories 移除掉,因为没必要再通过它来创建早期曝光的 bean 了.
装配完了,后面调 init-method, InitializingBean, BeanPostProcessor 等
getSingleton()时,singletonFactories 中没有 ObjectFactory.则会调 getSingleton() 创建单例 bean,由于在 singletonsCurrentlyInCreation 里有当前正在创建的 bean 记录,所以抛 BeanCurrentlyInCreationException 异常.
为什么没添加 ObjectFactory 到 singletonFactories 中,因为构造器方式 缺少
根据:单例 且 允许循环依赖 且 当前bean正在创建中,检测循环依赖,判断是否需要 提早暴露
这段逻辑