0%

循环依赖

循环依赖

spring中将循环依赖处理分为了两种情况

构造器循环依赖

使用构造器注入构成循环依赖,这种方式无法进行解决,抛出了BeanCurrentlyInCreationException异常

在创建bean之前会进行检测

1
2
3
4
5
6
7
protected void beforeSingletonCreation(String beanName) {
// inCreationCheckExclusions中是否存在当前正在创建的bean
// 并且singletonsCurrentlyInCreation是否可以添加成功(也就是singletonsCurrentlyInCreation中是否存在正在创建的bean)
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}

在创建bean之后会进行移除

1
2
3
4
5
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}

以TestA和TestB为例,由于构造器造成了循环依赖,所以在进行实例化TestA时(实例化TestA之前执行了beforeSingletonCreation方法,此时singletonsCurrentlyInCreation中添加TestA),需要TestB实例,所以需要实例化TestB(实例化TestB之前执行了beforeSingletonCreation方法,此时singletonsCurrentlyInCreation中添加TestB),然后在进行TestB时需要TestA实例,又需要进行实例化TestA,但是执行beforeSingletonCreation方法时,singletonsCurrentlyInCreation中已存在TestA,所以会抛出BeanCurrentlyInCreationException异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class TestA {

private TestB testB;

public TestA(TestB testB){
this.testB = testB;
}
}

public class TestB {
private TestA testA;

public TestB(TestA testA){
this.testA = testA;
}
}

setter循环依赖

对于setter注入造成的循环依赖,spring采用的是提前暴露刚完成的构造器实例化但未完成setter方法注入的bean来实现的,而且只能解决单例作用域的bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// ①doGetBean
// 获取bean
// allowEarlyReference是true,表示允许早期依赖
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从singletonObjects缓存中取
// singletonObjects中存的是beanName和bean实例
// singletonObjects是一级缓存
Object singletonObject = this.singletonObjects.get(beanName);
// 缓存中没有
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 锁定全局变量进行处理
synchronized (this.singletonObjects) {
// 如果该bean正在进行加载则不进行处理,直接返回
// earlySingletonObjects中存的是beanName和bean实例,但是与singletonObjects不同的是,存储的是还没进行属性注入操作的Bean的实例,,目的是为了监测循环引用
// earlySingletonObjects是二级缓存
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 从singletonFactories中获取,对于某些方法需要提前进行初始化时则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存在singletonFactories中
// singletonFactories中存的是beanName和创建bean的ObjectFactory工厂
// singletonFactories是三级缓存
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 调用ObjectFactory的getObject方法
singletonObject = singletonFactory.getObject();
// 放入到二级缓存中
// 记录在缓存earlySingletonObjects中,earlySingletonObjects和singletonFactories互斥,earlySingletonObjects与singletonObjects的不同之处在于当一个单例bean被放入该缓存后,那么其他的bean在创建过程中就能通过getBean方法获取到,目的是用来监测循环引用
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

// ②doGetBean
// 第一次创建,缓存中不存在,则会进行创建
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
// 创建bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});

// ③doCreateBean
if (instanceWrapper == null) {
// 创建bean实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}

// ④
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});

// 将ObjectFactory加入到三级缓存中
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);
}
}
}
// ⑤
// 调用applyPropertyValues(beanName, mbd, bw, pvs)来set值
populateBean(beanName, mbd, instanceWrapper);

// ⑥
// 整个bean实例创建并且属性注入后执行
// if (newSingleton) {
// addSingleton(beanName, singletonObject);
// }
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 加入一级缓存
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
// 移除二级缓存
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}

以TestA和TestB为例,创建单例TestA时,使用无参构造器进行创建,并将实例化的bean放入一个ObjectFactory中,存入到singletonFactories,用于返回提前暴露的bean,然后进行setter方法来注入TestB,此时还没有TestB,来创建单例TestB,使用无参构造器进行创建,并将实例化的bean放入一个ObjectFactory中,存入到singletonFactories,用于返回提前暴露的bean,然后进行setter来注入TestA,从ObjectFactory.getObject可以获取到testA,完成了TestB#setTestA方法,之后继续走TestA的逻辑,从而完成TestA#setTestB方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class TestA {

private TestB testB;

public TestB getTestB() {
return testB;
}

public void setTestB(TestB testB) {
this.testB = testB;
}
}

public class TestB {
private TestA testA;

public TestA getTestA() {
return testA;
}

public void setTestA(TestA testA) {
this.testA = testA;
}
}

总结一下

  • 一级缓存 singletonObjects 存放的是完全创建好的单例Bean
  • 二级缓存 earlySingletonObjects 存放的是完成实例化,但是还未进行属性注入的对象
  • 三级缓存 singletonFactories 提前暴露的一个单例工厂,二级缓存的对象就是通过这个单例工厂创建的

有个疑问

看上去好像二级缓存就可以解决循环依赖了,三级缓存的对象工厂的意义是什么呢?

来看一下不管有没有循环依赖,都会创建好一个对象,然后放入到三级缓存中

1
2
3
4
5
6
7
// 加入三级缓存
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});

只有调用三级缓存中的ObjectFactory.getObject()才会拿到对象,看一下getEarlyBeanReference干了什么吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// 使用后置处理器,这里做了个代理,也就是AOP (AbstractAutoProxyCreator继承的SmartInstantiationAwareBeanPostProcessor,也就是在getEarlyBeanReference方法中调用的wrapIfNecessary方法)
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
if (exposedObject == null) {
return null;
}
}
}
}
return exposedObject;
}

也就是做了个延迟代理的作用,在二级缓存里存放的其实是代理过的对象

欢迎关注我的其它发布渠道