SpringBean 循环依赖
# Spring Bean 循环依赖
## 为什么会存在循环依赖
<img src="https://oscimg.oschina.net/oscnet/up-4ac2f1ac005d007a18a0823719edb29abf7.png" width=300 height=168>
如上图👆所示,A对象的一个属性是B,B对象的一个属性是A,而Spring中的bean默认情况下都是单例的,所以这两个Bean就产生了循环依赖的问题!
>i 那么循环依赖的问题出现在什么情况呢
想一下属性赋值的方式有几种呢?
- 构造器赋值
> 这种形式循环依赖问题无法解决
- GET/SET方法
> 调用SET方法进行赋值的时候,可以通过三级缓存的策略来解决循环依赖的问题
所以,三级缓存的策略是针对于使用SET方法对属性赋值的场景下的!
## 循环依赖如何解决
<img src="https://oscimg.oschina.net/oscnet/up-eabac6749e665ea36856dce17c2119658a7.png">
在实例化的过程中,将处于半成品的对象全部放到缓存中,方便后续来进行调用;
只要有了当前对象的引用地址,那么后续来进行赋值即可;
>d 能不能将创建好的对象也放到缓存中呢?
不能,如果放在一起将无法区分对象是成品对象还是半成品对象了
所以再次引出多级缓存的概念,可以创建两个缓存对象,一个用来存放已经实例化的半成品对象,另一个存放完成实例化并且完成初始化的成品对象,这个应该比较好理解吧!
>i 思考一下以上的设计有没有问题呢?
### 为什么需要三级缓存?
Spring在解决对象Bean循环依赖的问题的解决方案是使用了「三级缓存」;
为什么需要三级缓存,也就是三个Map对象;
>i org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
```java
// 一级缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
// 二级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap(16);
// 三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
```
>w 三级缓存中分别保存的是什么内容
- 一级缓存: 成品对象
- 二级缓存: 半成品对象
- 三级缓存; lambda表达式
>w 如果只有二级缓存可不可行
在Spring源码中,只有addSingleton方法和doCreateBean方法中向三级缓存中添加东西的;
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory
```java
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);
}
}
```
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
```java
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
synchronized(this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
```
```java
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) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException var16) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
BeanCreationException ex = var17;
if (recordSuppressedExceptions) {
Iterator var8 = this.suppressedExceptions.iterator();
while(var8.hasNext()) {
Exception suppressedException = (Exception)var8.next();
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
```