一、简单聊一聊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、核心代码分析
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
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) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
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()) {
}
}
}
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
}
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异常。
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) {
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;
}
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
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异常。
|