Spring 解决循环依赖中时间长了容易模糊的点,记录下来方便看
三级缓存位置
public class DefaultSingletonBeanRegistry extends ... {
/**
* 一级缓存,缓存生成好的单例对象
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**
* 三级缓存,缓存『对已经实例化的Bean提前执行该Bean所有BeanPostProcessor』的延迟处理
*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/**
* 二级缓存,缓存已经实例化并提前执行完该Bean所有BeanPostProcessor的Bean(此时还未填充及初始化)
*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
}
Spring 处理 Bean 的主要流程
- 实例化 Bean,生成对象;
- 填充 Bean,处理 Bean 的属性依赖;
- 初始化 Bean,执行初始化方法、 BeanPostProcessor。
Spring 解决循环依赖的关键流程
DefaultSingletonBeanRegistry 类中,解决循环依赖的流程
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从单例对象(一级缓存)中获取
Object singletonObject = this.singletonObjects.get(beanName);
//不在一级缓存中,并且该Bean正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从提前执行完BeanPostProcessor的Bean的缓存(二级缓存)中获取
singletonObject = this.earlySingletonObjects.get(beanName);
//不在二级缓存中
if (singletonObject == null && allowEarlyReference) {
//获取该Bean的ObjectFactory(三级缓存),用于提前执行对该Bean的所有BeanPostProcessor
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//执行所有BeanPostProcessor
singletonObject = singletonFactory.getObject();
//加入二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
//移除三级缓存
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
为什么要缓存 ObjectFactory 的延迟处理
结合 Spring 对 Bean 的处理过程,正常情况下 BeanPostProcessor 的执行是在初始化的时候去做,而且并不是所有 Bean 都有 AOP(增强旧对象,返回增强后的新对象)的需求,只有在遇到循环依赖的场景,才需要提前执行 BeanPostProcessor,以便能让其他 Bean 获取到增强后的 Bean。
所以让所有 Bean 都提前执行 BeanPostProcessor 是不合适的,缓存了 ObjectFactory 之后,如果遇到循环依赖就调用(提前增强),没有遇到循环依赖就不调用(走正常的 Bean 的处理过程),这样是比较合理的。
singletonFactories 在什么时机缓存和移除
-
缓存:
AbstractAutowireCapableBeanFactory#doCreateBean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
DefaultSingletonBeanRegistry 类中缓存 singletonFactories
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { //这里 this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }
AbstractAutowireCapableBeanFactory 类中获取 SmartInstantiationAwareBeanPostProcessor 并执行
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; }
-
移除
DefaultSingletonBeanRegistry 类中,正常 Bean 流程
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); } }
DefaultSingletonBeanRegistry 类中,解决循环依赖的流程
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; }
为什么需要 earlySingletonObjects
earlySingletonObjects 存的是已经实例化并提前执行完该 Bean 所有 BeanPostProcessor 的 Bean,但此时 Bean 还未填充,如果没有 earlySingletonObjects,下面这个场景会出现问题:
@Component
public class B {
@Autowired
private A a;
}
@Component
public class A {
@Autowired
private B b1;
@Autowired
private B b2;
}
- 对 A 执行填充时,先处理 b1 属性,此时 B 在 singletonObjects 不存在,所以先实例化 B,再从 singletonFactories 中查找到 B 的提前执行 BeanPostProcessor 的 ObjectFactory,调用 getObject 获取到提前执行 BeanPostProcessor 的增强 B 实例,注入到 b1 属性中;
- 到了 b2 这个属性时,由于 B 在 singletonObjects 中还是不存在,所以仍然需要获取 B 的 ObjectFactory,执行 getObject,导致又对 B 执行了一遍 BeanPostProcessor。
所以为了处理多次引用的问题,需要这个中间状态的缓存容器 earlySingletonObjects,用来缓存实例化之后又提前执行了 BeanPostProcessor 的 Bean,此时 b2 可以直接从 earlySingletonObjects 中去获取,不会重复执行 ObjectFactory 的 getObject 方法。
earlySingletonObjects 在什么时机缓存和移除
-
缓存
DefaultSingletonBeanRegistry 类中,解决循环依赖的流程
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; }
-
移除
DefaultSingletonBeanRegistry 类中,正常 Bean 流程
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); } }
DefaultSingletonBeanRegistry 类中,缓存 ObjectFactory 时
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { this.singletonFactories.put(beanName, singletonFactory); //这里 this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }
如何避免 BeanPostProcessor 重复执行
结合 Spring 对 Bean 的处理过程,在解决循环依赖的时候,Bean 在填充阶段,已经提前执行了 singletonFactories 中的「对该 Bean 提前执行所有的 BeanPostProcessor」方法,但在 Bean 初始化时还会再次执行 BeanPostProcessor,所以会导致执行两次。
Spring 提供了 SmartInstantiationAwareBeanPostProcessor 接口,需要增强 Bean 的 BeanPostProcessor 可以实现此接口, 并增加一个缓存,用来存储已经增强的 Bean ,每次调用该 BeanPostProcessor 的时候,如果缓存中已经存在那就说明创建过了,直接返回上次创建的即可,避免重复增强。
Spring 无法解决什么场景的循环依赖
构造器注入的场景无法解决,因为构造器注入的时候 Bean 还未完成实例化,更别提放入缓存了,没放入缓存就无法解决循环依赖问题。
setter 注入平日不使用,不做研究。
举个栗子🌰
结合一个具体的场景,A 和 B 互相依赖,处理过程如下:
@Component
public class A {
@Autowired
private B b;
}
@Component
public class B {
@Autowired
private A a;
}
-
开搞,此时缓存中啥也没有
singletonObjects(一级) earlySingletonObjects(二级) singletonFactories(三级) -
缓存中不存在 A,所以实例化 A,生成了 a1 对象,在三级缓存中添加对 a1 执行所有 BeanPostProcessor 的延迟处理
singletonObjects(一级) earlySingletonObjects(二级) singletonFactories(三级) A → ObjectFactory(a1)
-
对 a1 进行填充,发现了 B 的引用,要对 a1 中的 b 对象进行注入,同样地缓存中不存在 B,也是先实例化 B,生成了 b1 对象,在三级缓存中添加对 b1 执行所有 BeanPostProcessor 的延迟处理
singletonObjects(一级) earlySingletonObjects(二级) singletonFactories(三级) A → ObjectFactory(a1)
B →ObjectFactoty(b1)
-
对 b1 进行填充,发现了 A 引用,前两级缓存中没有 A,三级缓存中找到了 A 的 ObjectFactory 并执行,将返回的结果
Proxy$a1
(增强后的a1) 放入二级缓存中,同时在三级缓存中移除 AsingletonObjects(一级) earlySingletonObjects(二级) singletonFactories(三级) A → Proxy$a1
B → ObjectFactoty(b1)
-
将
Proxy$a1
注入到 b1 对象的 a 属性,B 填充完成,执行初始化、BeanPostProcessor 后,完成创建单例过程,放入一级缓存中,移除 B 的三级缓存注意:如果 BeanPostProcessor 有增强 b1,则一级缓存中缓存的为
Proxy$b1
,否则为 b1ingletonObjects(一级) earlySingletonObjects(二级) singletonFactories(三级) B → Proxy$b1
A → Proxy$a1
-
将
Proxy$b1
注入到 a1 的 b 属性,a1 对象填充完毕,执行初始化、BeanPostProcessor,因为有 SmartInstantiationAwareBeanPostProcessor 的存在,最终增强后的对象仍然是Proxy$a1
,完成 A 的单例创建,添加到一级缓存,从二级缓存中移除ingletonObjects(一级) earlySingletonObjects(二级) singletonFactories(三级) B → Proxy$b1
A →Proxy$a1
-
两个对象创建完毕