您好,登录后才能下订单哦!
# Spring源码分析之如何解决循环依赖
## 目录
1. [引言](#引言)
2. [什么是循环依赖](#什么是循环依赖)
3. [Spring中的循环依赖场景](#spring中的循环依赖场景)
4. [Spring解决循环依赖的核心设计](#spring解决循环依赖的核心设计)
5. [三级缓存机制详解](#三级缓存机制详解)
6. [源码深度剖析](#源码深度剖析)
7. [循环依赖的局限性](#循环依赖的局限性)
8. [实际开发中的建议](#实际开发中的建议)
9. [总结](#总结)
## 引言
在Spring框架的使用过程中,循环依赖(Circular Dependency)是一个常见但又容易引发问题的话题。Spring通过巧妙的设计解决了大部分循环依赖场景,但其内部实现机制却鲜为人知。本文将深入Spring源码(以5.3.x版本为例),剖析Spring如何通过三级缓存机制解决循环依赖问题。
## 什么是循环依赖
### 基本概念
循环依赖是指两个或多个Bean相互依赖,形成闭环引用关系:
```java
// 示例1:直接循环依赖
class A {
@Autowired B b;
}
class B {
@Autowired A a;
}
// 示例2:间接循环依赖
class X {
@Autowired Y y;
}
class Y {
@Autowired Z z;
}
class Z {
@Autowired X x;
}
@Service public class ServiceB { private final ServiceA serviceA; public ServiceB(ServiceA serviceA) { this.serviceA = serviceA; } }
启动时会抛出`BeanCurrentlyInCreationException`
2. **prototype作用域的循环依赖**
```java
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Service
public class PrototypeA {
@Autowired private PrototypeB b;
}
Spring通过三级缓存解决循环依赖问题:
缓存级别 | 名称 | 存储内容 |
---|---|---|
第一级缓存 | singletonObjects | 完全初始化好的Bean |
第二级缓存 | earlySingletonObjects | 提前暴露的原始Bean(未填充属性) |
第三级缓存 | singletonFactories | 单例工厂ObjectFactory |
DefaultSingletonBeanRegistry
:缓存管理的核心类AbstractAutowireCapableBeanFactory
:Bean创建的主要逻辑SmartInstantiationAwareBeanPostProcessor
:AOP代理相关处理graph TD
A[开始创建BeanA] --> B[实例化A]
B --> C[将A的ObjectFactory放入三级缓存]
C --> D[填充A的属性]
D --> E[发现依赖BeanB]
E --> F[开始创建BeanB]
F --> G[实例化B]
G --> H[将B的ObjectFactory放入三级缓存]
H --> I[填充B的属性]
I --> J[发现依赖BeanA]
J --> K[从三级缓存获取A的ObjectFactory]
K --> L[执行getEarlyBeanReference]
L --> M[将A的半成品放入二级缓存]
M --> N[返回A的早期引用给B]
N --> O[完成B的初始化]
O --> P[将B放入一级缓存]
P --> Q[返回B的引用给A]
Q --> R[完成A的初始化]
R --> S[将A放入一级缓存]
DefaultSingletonBeanRegistry#getSingleton
:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 1. 检查一级缓存
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 2. 检查二级缓存
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 3. 检查三级缓存
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
:
protected Object doCreateBean(/*...*/) {
// 实例化Bean
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
// 将ObjectFactory加入三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
// 填充属性
populateBean(beanName, mbd, instanceWrapper);
// 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
return exposedObject;
}
public void refresh() {
// ...
finishBeanFactoryInitialization(beanFactory);
// ...
}
public void preInstantiateSingletons() {
for (String beanName : beanNames) {
getBean(beanName);
}
}
protected <T> T doGetBean(/*...*/) {
// 检查缓存
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null) {
return (T) sharedInstance;
}
// 创建Bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
return createBean(beanName, mbd, args);
});
}
}
当存在AOP代理时,getEarlyBeanReference
会通过AbstractAutoProxyCreator
提前生成代理对象:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
exposedObject = ((SmartInstantiationAwareBeanPostProcessor) bp)
.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
在构造器注入场景下,Bean尚未创建完成就无法放入缓存,导致无法解决循环依赖:
protected BeanWrapper createBeanInstance(/*...*/) {
// 构造器注入会直接尝试获取依赖Bean
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, args); // 这里会立即解析参数
}
}
每次获取prototype bean都会创建新实例,Spring无法管理这种场景下的循环依赖:
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanCurrentlyInCreationException:
-Dspring.main.allow-circular-references=true
(Spring Boot 2.6+)代理对象异常:
@Async
等注解的使用Spring通过三级缓存机制(singletonFactories、earlySingletonObjects、singletonObjects)巧妙地解决了单例Bean的setter/field注入循环依赖问题。其核心思想是:提前暴露未完全初始化的Bean引用。理解这一机制对于:
都有重要意义。然而,开发者应当意识到这是框架提供的”安全网”,而非鼓励循环依赖的设计模式。
附录:相关源码类图
classDiagram
class DefaultSingletonBeanRegistry{
+Map<String,Object> singletonObjects
+Map<String,Object> earlySingletonObjects
+Map<String,ObjectFactory<?>> singletonFactories
+getSingleton(String beanName)
+addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory)
}
class AbstractAutowireCapableBeanFactory{
+doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args)
+createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args)
+populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw)
}
DefaultSingletonBeanRegistry <|-- AbstractAutowireCapableBeanFactory
(全文约13,300字,实际字数可能因格式调整略有变化) “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。