Spring 循环依赖与三级缓存源码解析
1. 循环依赖问题
循环依赖指两个或多个 Bean 相互依赖,形成闭环。例如,Bean A 依赖 Bean B,而 Bean B 又依赖 Bean A。
2. Spring 的三级缓存机制
Spring 通过三级缓存解决循环依赖问题,三级缓存分别为:
- 一级缓存(singletonObjects):存储完全初始化好的单例 Bean。
- 二级缓存(earlySingletonObjects):存储提前暴露的 Bean(已实例化但未完全初始化)。
- 三级缓存(singletonFactories):存储 Bean 的 ObjectFactory,用于生成提前暴露的 Bean。
3. 为什么需要三级缓存而非两级?
-
两级缓存的局限性:
- 如果只有一级和二级缓存,无法处理代理对象的循环依赖。代理对象需要在对象创建后生成,而两级缓存无法保证代理对象的正确注入。
-
三级缓存的作用:
- 三级缓存通过 ObjectFactory 延迟生成代理对象,确保在需要时生成正确的代理对象,从而解决代理对象的循环依赖问题。
4. 源码解析
- DefaultSingletonBeanRegistry 类:
getSingleton(String beanName, boolean allowEarlyReference)
方法负责从缓存中获取 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;
}
- AbstractAutowireCapableBeanFactory 类:
doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args)
方法负责 Bean 的创建和初始化。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 提前暴露 Bean,解决循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
} catch (Throwable ex) {
// 异常处理
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
}
}
return exposedObject;
}
- addSingletonFactory 方法:
- 将 Bean 的 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);
}
}
}
5. 总结
Spring 使用三级缓存解决循环依赖问题,确保代理对象能正确生成和注入。三级缓存通过 ObjectFactory 延迟生成代理对象,避免了两级缓存的局限性。