1. 背景知识
(1) spring(3) - springboot启动过程
(2) spring(4) - spring Bean创建并注册到容器
2. Bean创建
通过 背景知识,我们知道,spring在创建Bean的时候,分三步,先创建bean,然后注册到容器中,之后进行属性装配,在进行初始化
2.1 AbstractAutowireCapableBeanFactory 类的 doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
方法
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// ① 创建实例wapper
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
}
mbd.postProcessed = true;
}
}
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
// ③ 将该实例放到容器缓存中
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
// ④ 为实例wapper装配属性
this.populateBean(beanName, mbd, instanceWrapper);
// ⑤ 为实例wapper进行初始化
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
......
}
2.2 进入 // ③ 将该实例放到容器缓存中
处 this.addSingletonFactory(..)
方法
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized(this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
我们看到,此处逻辑为 将该实例放到了 singletonFactories 属性中,并将 singletonFactories 属性中的引用移出掉了,这两个属性是什么意思呢?
点击其中一个属性,我们看下属性的声明 ,发现这几个属性都属于父类 DefaultSingletonBeanRegistry ,那就明白啦 , 这个类就是处理spring Bean 容器处理缓存的类,如下 :
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
// 第一级缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
// 第三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
// 第二级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap(16);
....
}
一级缓存singletonObjects是完整的bean,它可以被外界任意使用,并且不会有歧义。
二级缓存earlySingletonObjects是不完整的bean,没有完成初始化,它与singletonObjects的分离主要是职责的分离以及边界划分;
三级缓存singletonFactories,其职责就是包装一个bean,有回调逻辑,所以它的作用非常清晰,并且只能处于第三层。
3 应用三层缓存对循环依赖的处理举例
如果 A,B 两个类互相依赖,且需要实例化,当只有一层缓存 singletonObjects
的时候,A 实例化调用B,B实例化调用A,就无法结束了;
此时加一层缓存 earlySingletonObjects
,用于存储还未完成初始化的实例,但是已经完成了创建,在创建A的时候,发现需要创建B,就去创建B,找B的时候一次从 第一级缓存,二级缓存,三级缓存中找, 最后在三级缓存singletonFactories
中找到其工厂,直接创建B 的未初始化实例放到二级缓存中,并将三级缓存中的B工厂清除,然后返回继续实例化A,因为从二级缓存中找到了B的未初始化引用,得以继续完成实例化A,当需要继续初始化B时,再将A的完整实例引用从一级缓存给到B实例,这样就完成了循环依赖的实例化;
根本原理是 从JVM层面,将实例化分成了 声明, 初始化 两个阶段,(也就是分层的思想),在一层无法解决的时候,通过引入分层解决问题;