Spring循环依赖
什么是循环依赖
两个或两个以上的bean,互相持有,形成闭环。例如:A依赖B,B依赖C,C依赖A;形成相互依赖。
Spring中循环依赖
-
构造方法中的循环依赖。
@Component public class TestA { private TestB testB; TestA (TestB testB) { this.testB = testB; } } @Component public class TestB { private TestA testA; TestB(TestA testA) { this.testA = testA; } } Description: The dependencies of some of the beans in the application context form a cycle: ┌─────┐ | testA defined in file [H:\strive\target\classes\com\spring\circleDepend\TestA.class] ↑ ↓ | testB defined in file [H:\strive\target\classes\com\spring\circleDepend\TestB.class] └─────┘
可以看到spring是不能解决这种构造方法的循环依赖问题。因为创建当前对象的时候,需要调用当前对象的构造方法,由于带参的构造方法,总是互相持有,所以不能创建成功。
-
setter中的循环依赖。循环依赖只是在属性中,不在构造方法中。
@Component public class TestA { @Autowired private TestB testB; } @Component public class TestB { @Autowired private TestA testA; }
这种境况是可以成功创建对象的。
Spring是如何解决循环依赖的
Spring默认一级缓存是存放所有已完成初始化的bean的。
- 二级缓存
看一下Spring创建bean的简易过程
所以我们只需要在创建bean实例的时候,提前把bean加入到缓存,让bean尽早的暴露,循环依赖在获取bean的进行属性填充的时候,可以先在缓存中直接拿到bean的引用进行属性填充。
二级缓存的问题:如果此时TestA创建完成之后,又需要生成TestA的代理类ProxyTestA,但是此时TestB中testA的属性还是原有的TestA的引用,而不是代理类ProxyTestA,就会导致TestB中属性不是一个对象。
-
三级缓存
三级缓存,多了一级缓存来存放生成bean的工厂。
Spring源码解析
第一级缓存(也叫单例池):Map<String, Object> singletonObjects,存放已经经历了完整生命周期的 Bean 对象
第二级缓存:Map<String, Object> earlySingletonObjects,存放早期暴露出来的 Bean 对象,Bean 的生命周期未结束(属性还未填充完),可能是代理对象,也可能是原始对象
第三级缓存:Map<String, ObjectFactory<?>> singletonFactories,存放可以生成 Bean 的工厂,工厂主要用来生成 Bean 的代理对象
// 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.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}
// lamnada lazy加载
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 如果bean的后置处理PostProcessors有的话,需要执行所有的后置处理,来得到一个期望的bean,生成一个代理类
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,就加入到三级缓存中(加入的是创建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);
}
}
}
// 获取这个bean的单例的时候
// 如果一级缓存中没有,就从二级缓存中获取,二级缓存中没有就去三级缓存中获取
// 从三级缓存中获取创建bean的factory,从factory拿到bean,移除三级缓存中的bean,加入到二级缓存。
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;
}