循环依赖
两个或两个以上对象互相依赖对方,形成一个依赖环,例如A对象依赖B对象,B对象依赖A对象。
当创建相互依赖的对象时,会形成死循环,例如下图无缓存中的情况。而Spring通过增加缓存,将未完全创建好的A提前暴露在缓存中,当相互依赖的对象B对属性A赋值时,可以直接从缓存中获取A,而不需要再创建A,例如下图有缓存中的情况。
Spring的三级缓存
Spring的三级缓存分别为:
- singletonObject:一级缓存,缓存中的bean是已经创建完成的,该bean经历过实例化->属性填充->初始化以及各种的后置处理。因此,一旦需要获取bean时,会优先寻找一级缓存
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
// ...
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// bean创建前操作,标记当前bean正在创建
beforeSingletonCreation(beanName);
boolean newSingleton = false;
try {
// 创建bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (Exception ex) {
// ...
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// bean创建后操作,删除当前bean正在创建
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 存入一级缓存
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
// 在bean创建完成之后,将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);
}
}
- earlySingletonObjects:二级缓存,该缓存跟一级缓存的区别在于,该缓存所获取到的bean是提前曝光出来的,是还没创建完成的。也就是说获取到的bean只能确保已经进行了实例化,但是属性填充跟初始化还没有做完,因此该bean还没创建完成,时半成品,仅仅能作为指针提前曝光,被其他bean所引用
// 二级缓存是从三级缓存中通过getObject()方法获取的
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 三级缓存通过getObject()方法获取半成品bean
singletonObject = singletonFactory.getObject();
// 存放二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
- singletonFactories:三级缓存,在bean实例化完之后,属性填充以及初始化之前,如果允许提前曝光,spring会将实例化后的bean提前曝光,也就是把该bean转换成
beanFactory
并加入到三级缓存。在需要引用提前曝光对象时再通过singletonFactory.getObject()
获取。
// 在实例化bean之后,如果允许循环依赖,将未创建完的bean加入到三级缓存
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 存入三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
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);
}
}
}
三级缓存的使用
当A和B相互依赖时,若先创建实例A,则整个调用过程为:
其中涉及缓存和依赖相关主要过程为:
- 开始创建实例A,标记A为正在创建
protected void beforeSingletonCreation(String beanName) {
// 将实例A加入到singletonsCurrentlyInCreation中
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
- 实例化A后,将未赋值和初始化的实例A加入到三级缓存singletonFactories中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
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);
// 二级缓存删除该bean
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
- 由于循环依赖,实例A触发实例B加载,标记B为正在创建,并在实例化B后,将未赋值和初始化的实例B加入到三级缓存singletonFactories中(同上)
- 由于循环依赖,实例B触发实例A加载,在缓存中获取到未创建好的A
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 一级缓存中不存在A,返回null
Object singletonObject = this.singletonObjects.get(beanName);
// A因为已经标记为正在创建,进入下面的if语句
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 二级缓存不存在A,返回null
singletonObject = this.earlySingletonObjects.get(beanName);
// 允许循环依赖
if (singletonObject == null && allowEarlyReference) {
// 锁定一级缓存和二级缓存,并再次检验
synchronized (this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 三级缓存中存在未创建好的实例A,获取到ObjectFactory对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 调用getObject()方法,获取到为创建好的实例A
singletonObject = singletonFactory.getObject();
// 将实例A放入到二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
// 三级缓存中删除实例A
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
- 在B创建好之后,则标记实例B创建完成,并将B加入到一级缓存中
protected void afterSingletonCreation(String beanName) {
// 将实例B从singletonsCurrentlyInCreation中删除
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 将实例B放入一级缓存
this.singletonObjects.put(beanName, singletonObject);
// 三级缓存中删除B
this.singletonFactories.remove(beanName);
// 二级缓存中删除B
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
- 在A创建好之后,则标记实例A创建完成,并将A加入到一级缓存中
AOP和三级缓存
不涉及AOP
实例加入到三级缓存,并从三级缓存中获取实例过程如下:
// 添加到三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
// 使用三级缓存
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
从三级缓存获取到的bean,是经过getEarlyBeanReference()作用之后返回的bean,在不涉及AOP时,没有类覆盖实现getEarlyBeanReference()方法,使用getEarlyBeanReference()的默认实现,因此返回的bean就是实例化后的原始bean。
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
}
涉及AOP
当涉及到AOP时,AbstractAutoProxyCreator实现了getEarlyBeanReference()方法,返回的bean是经过AOP代理的bean。
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
// 创建AOP代理
return wrapIfNecessary(bean, beanName, cacheKey);
}
不涉及循环依赖时,bean的AOP代理是在实例化,赋值,初始化之后创建的。而涉及循环依赖时,三级缓存中保存的是实例化但未赋值,初始化之后的bean,当通过三级缓存获取实例时,则会提前创建AOP代理:
- 非循环依赖,在实例化,赋值,初始化之后创建AOP代理
- 循环依赖,在实例化,未赋值,初始化之后创建AOP代理(提前创建代理)
对于在缓存中提前创建好代理的实例,当赋值,初始化之后,运行至bean的后置处理逻辑,即AbstractAutoProxyCreator的postProcessAfterInitialization方法(正常创建AOP代理逻辑)时,则不会再次创建AOP代理,返回的是不经代理的bean。
// AbstractAutoProxyCreator的后置处理逻辑
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 由于提前创建了代理并且有缓存,则不再返回代理
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
再返回赋值和初始化bean的逻辑中,exposedObject作为最终的返回结果,在使用到AOP时,最终返回的都是代理bean
// 原始bean
Object exposedObject = bean;
try {
// 实例赋值
populateBean(beanName, mbd, instanceWrapper);
// 实例初始化(初始化后调用bean的后置处理逻辑,即创建AOP代理)
// (1)非循环依赖,未提前创建代理,initializeBean返回的是代理bean
// (2)循环依赖,提前创建代理,initializeBean返回的是原始bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
if (earlySingletonExposure) {
// 当allowEarlyReference=false时,只能从一级二级缓存中获取实例
// (1)未提前创建代理时,实例在三级缓存中,getSingleton返回代理null
// (2)提前创建代理时,实例在二级缓存中,返回代理bean
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
// 提前创建代理,代理bean在缓存中,所以下面相等
if (exposedObject == bean) {
// 将代理bean赋值给exposedObject
exposedObject = earlySingletonReference;
}
// ...
}
}