一、简单聊一聊bean的生命周期
1.1、名词讲解
springfactory中的三级缓存
singletonObjects【一级】、earlySingletonObjects【二级】、singletonFactories【三级】
三级缓存分别作用:
一级:存储经历过完整bean的生命周期后的对象
二级:在属性注入情况下存在循环依赖情况,保证对象的单例
三级:打破循环依赖,其内部存储为bean名称+普通对象
1.2、案例分析
假设有三个类A、B、C
生命A对象生命周期
1、根据构造方法反射生成未初始化对象A —>并将生成的对象存储到三级缓存singletonFactories中
2、属性填充B(B不存在对A的属性依赖)
3、属性填充完毕后执行:aware相关接口、初始化前、初始化、初始化后(可能执行aop生成代理对象)
4、将执行完生命周期后的bean存放到singletonObjects中
1.3、核心代码分析
//AbstractAutowireCapableBeanFactory.doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//先初始化生成对象,一般情况下通过默认构造方法生成
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
//。。。。
//作为判断依据为存放三级缓存
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
//将未初始化的bean对象存放到三级缓存中,存储的未beanName + lambda表达式
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
//最终生成对象bean
Object exposedObject = bean;
try {
//对象属性填充
populateBean(beanName, mbd, instanceWrapper);
//属性填充完毕后执行:aware相关接口、初始化前、初始化、初始化后(可能执行aop生成代理对象)
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
//。。。。
}
//正常情况下earlySingletonExposure==true
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//相等说明未进行aop操作
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
//。。。。
}
}
}
// 主要包含注册 destroy method
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
//。。。
}
//返回最终对象bean,两种情况:aop之后的代理bean、普通bean
return exposedObject;
}
二、为什么会存在构造方法注入属性时存在循环依赖报错
@Component
class A {
private B b;
private C c;
public A(B b,C c){...}
}
@Component
class B {
@Autowired
private A a;
}
@Component
class C {
@Autowired
private A a;
}
案例分析:
1、初始化生成A对象时发现内部仅有一个有参构造方法,故选择其进行class反射,故去ioc容器中寻找B、C的对象进行属性注入。但请注意在该过程中还未生成A的初始化前对象,也就是说初始化前的对象A还未存储对第三级缓存中,故此时在AbstractBeanFactory.doGetBean方法会执行else方法体,即创建新的对象。
2、在ioc容器中寻找B、C时发现其还未创建。故通过空构造方法进行构造对象b、c。紧接着进行属性注入A,但在ioc容器中发现其不存在,故又进入创建A对象,但此时发现A对象正在创建中,从而报BeanCurrentlyInCreationException异常。
//DefaultSingletonBeanRegistry.getSingleton /** 执行流程: 1.从一级缓存singletonObjects中获取对象 2.若存在则直接返回,不存在则首先执行beforeSingletonCreation方法将当前创建bean对象记录 到singletonsCurrentlyInCreation中,若不存在循环依赖则执行singletonFactory.getObject(); 进行创建bean对象并返回结果 3.但存在循环依赖情况下会进行 if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); }方法中的!this.singletonsCurrentlyInCreation.add(beanName)为true进而抛出异常 */ public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { //.... beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } //DefaultSingletonBeanRegistry.beforeSingletonCreation protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } } //DefaultSingletonBeanRegistry.afterSingletonCreation protected void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); } }
结论
构造方法中存在循环依赖时由于不能在三级缓存中获取普通对象,从而导致循环创建对象报BeanCurrentlyInCreationException异常。