一、介绍
提前曝光bean的Object-Factory是spring为了解决bean循环依赖的一种方法。
- 什么是循环依赖
spring加载一个bean需要两个步骤:1.创建bean;2.给这个bean填充属性
如上图,加载类A的步骤为:
- 先创建A,然后给A填充属性的时候,发现A依赖一个类B属性,所以去加载B;
- 创建B,然后给B填充属性的时候,发现B依赖一个类C属性,所以去加载C;
- 创建C,然后给C填充属性的时候,发现C依赖一个A属性,所以又会去加载A。。。
这样就形成了没完没了的循环依赖!
- 解决办法:提前曝光bean的Object-Factory
当创建一个bean之后,不等执行填充属性这个步骤,就把该bean实例存入到一个Map中(DefaultSingletonBeanRegistry#singletonFactories),创建一个bean时,就先去这个Map中查找有没有对应的bean实例已经创建了,如果有的话直接就属性填充完成了。
spring只解决了单例中,setter注入引起的循环依赖问题。原型bean和构造器注入引起的循环依赖问题不能解决。
二、bean加载流程
- 获取用户传入name对应的beanName
- 尝试从缓存中获取bean实例
- 缓存中不存在,加载bean实例
3.1. 检查循环依赖
3.2 处理parentBeanFactory
3.3 处理依赖的bean(dependsOn)
3.4 三种bean实例的创建
3.4.1 单例bean的创建
3.4.1.1 获取单例bean,getSingleton()方法
3.4.1.2 准备创建bean,createBean()方法
3.4.1.3 创建bean,doCreateBean()方法
3.4.1.3.1 创建BeanWrapper
3.4.1.3.2 记录bean的Object-Factory(本章解析)
3.4.2 原型bean的创建
3.4.3 根据scope策略创建bean - 从bean实例中获取真正的对象
- 转换对象类型
- 返回对象实例
三、相关类及方法
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean:创建bean流程
- org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory:提前曝光bean
- org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference:获取提前依赖的bean(循环依赖的情况使用)
四、源码分析
1. 提前曝光单例bean
// 单例&&允许循环引用&&该bean在创建中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
// 需要提早曝光单例
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 把创建实例的ObjectFactory加入单例工厂
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
// 创建bean实例的ObjectFactory加入到singletonFactories
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
- 创建中的beanName
保存在DefaultSingletonBeanRegistry#singletonsCurrentlyInCreation中。执行保存bean状态的代码逻辑在DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>),创建bean之前会把该bean保存到singletonsCurrentlyInCreation,创建完成之后从singletonsCurrentlyInCreation移除。 - 提前曝光的bean
该bean保存在DefaultSingletonBeanRegistry#singletonFactories,用来解决循环依赖。
2. 获取提前曝光的bean
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
// 应用SmartInstantiationAwareBeanPostProcessor
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
这个方法的入参bean,其实已经是创建好的bean实例了。经过这个方法是为了给用户自定义的SmartInstantiationAwareBeanPostProcessor一个机会,来根据自己的需要制定一个需要的bean。