原文网址:Spring--循环依赖的原理(三)--原理概述_IT利刃出鞘的博客-CSDN博客
简介
说明
本文介绍Spring(SpringBoot)解决循环依赖的流程。
文章系列
- Spring--循环依赖的原理(一)--什么是循环依赖_IT利刃出鞘的博客-CSDN博客
- Spring--循环依赖的原理(二)--打断点分析_IT利刃出鞘的博客-CSDN博客
- Spring--循环依赖的原理(三)--原理概述_IT利刃出鞘的博客-CSDN博客
- Spring--循环依赖的原理(四)--为什么用三级缓存,而不是二级_IT利刃出鞘的博客-CSDN博客
三级缓存流程
- 从一级缓存singletonObjects中获取。()
- 若一级缓存中获取不到,则从二级缓存earlySingletonObjects中获取
- 若二级缓存中获取不到,则从三级缓存singletonFactories中获取
- 通过beanName获得对应的ObjectFactory,若能够获取到,则:
- 调用ObjectFactory#getObject获得真正的bean
- 把此bean从三级缓存移到二级缓存。即:singletonFactories中移除,并放入earlySingletonObjects中。
- 通过beanName获得对应的ObjectFactory,若能够获取到,则:
DefaultSingletonBeanRegistry 里边的三级缓存对应的map,如下所示:
/** Cache of singleton objects: bean name to bean instance. */
// 缓存单例Bean。key:bean名字,value:bean实例
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of early singleton objects: bean name to bean instance. */
// 缓存半成品单例Bean。key:bean名字,value:bean实例(已实例化,但未注入属性和初始化)
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** Cache of singleton factories: bean name to ObjectFactory. */
// 缓存单例bean的工厂。key:bean名字,value:能够生成bean的工厂
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
代码位置
从上边可以追踪到从缓存中获取bean的位置:DefaultSingletonBeanRegistry#getSingleton(String beanName, boolean allowEarlyReference)
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName); // 一级缓存
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName); // 二级缓存
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); // 三级缓存
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
bean何时被加入第3级缓存?
简介
在上边“4.三级缓存”中可以看到,第三级缓存(singletonFactories)里边放入了以bean名为键,ObjectFactory为值的项。那么,是何时放入的呢?
答:在AbstractAutowireCapableBeanFactory#doCreateBean中,populateBean之前放入的,方法为:addSingletonFactory
doCreateBean //AbstractAutowireCapableBeanFactory
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
addSingletonFactory //DefaultSingletonBeanRegistry
// 放入以bean名为键,ObjectFactory为值的项
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);
}
}
}
getEarlyBeanReference //AbstractAutowireCapableBeanFactory
// 返回 A 的引用。(虽然 A 还在创建,未完成。)
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 ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
三级缓存流程图
流程图
总结
- 对于不同的bean,获取某个循环依赖的对象的位置是不同的。
- 对于第一次获取:缓存中没有,会去创建它,然后获取。
- 对于第二次获取:第3级缓存中有,会从第3级缓存中获取,然后将其转移到第2级缓存
getSingleton(String beanName, ObjectFactory<?> singletonFactory)
代码流程:
入口
getSingleton(String beanName, ObjectFactory<?> singletonFactory) //DefaultSingletonBeanRegistry
// DefaultSingletonBeanRegistry
singletonObject = singletonFactory.getObject();
addSingleton(beanName, singletonObject);addSingleton(String beanName, Object singletonObject) // DefaultSingletonBeanRegistry
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}