• java
  • go
  • 数据库
  • linux
  • 中间件
  • 书
  • 源码
  • 夕拾

  • java
  • go
  • 数据库
  • linux
  • 中间件
  • 书
  • 源码
  • 夕拾

spring循环依赖问题

spring循环依赖问题

  • spring循环依赖问题
    • 循环依赖问题的产生
    • spring中的解决方案
    • 各级缓存的值及设置
      • 三级缓存
      • 二级缓存
      • 一级缓存
  • bean创建的整体流程在此不表。只摘录部分代码及流程

循环依赖问题主要主要ConfigurableListableBeanFactory中对单例bean的预加载中解决。
ConfigurableListableBeanFactory中提供bean definition的解析,注册,对单例的预加载.

  • 以上可知,其实spring只解决了单例bean的循环依赖,其他的,spring也没办法,抛异常

循环依赖问题的产生

  1. Bean互相依赖
  2. 构造器互相依赖
  3. 属性互相依赖
    ….

spring中的解决方案

创建与初始化完毕分割开,增加多级缓存处理

  1. A依赖B,A先创建,并将自己放在缓存中
  2. B开始创建,发现依赖C,处理同1
  3. C开始创建,发现依赖A,可以引用早期A的缓存,然后继续初始化。完毕之后将自己添加到一级缓存中。

各级缓存的值及设置

三级缓存

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
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
// Eagerly check singleton cache for manually registered singletons.
// 从缓存中取,缓存中的bean是只被实例化了,还没有初始化
Object sharedInstance = getSingleton(beanName);
//
if (sharedInstance != null && args == null){
...
} else { ... }

// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {...}
return (T) bean;

}

public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}


/**
* Return the (raw) singleton object registered under the given name.
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or {@code null} if none found
*/
/**
* 整体流程:
* 1. 从singletonObjects缓存中获取。
* 2. 当前指定的beanName正在创建,从earlySingletonObjects中取
* 3. 还是没取到,且允许 allowEarlyReference ,则从bean工厂中取,然后加入早期bean缓存,从工厂缓存中移除。
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从单例中加载bean
Object singletonObject = this.singletonObjects.get(beanName);
// 缓存中的不存在,且正在创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 上锁先
synchronized (this.singletonObjects) {
// 从earlySingletonObjects中获取
singletonObject = this.earlySingletonObjects.get(beanName);
// earlySingletonObjects中没有,且允许提前创建
if (singletonObject == null && allowEarlyReference) {
// 获取对应的bean工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 获取bean
singletonObject = singletonFactory.getObject();
// 放入earlySingletonObjects缓存
this.earlySingletonObjects.put(beanName, singletonObject);
// 从singletonFactories移除对应的facotry
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
  • 关于 singletonObjects、earlySingletonObjects、singletonFactories
1
2
3
4
5
6
7
8
9
10
11
12
13

/** Cache of singleton objects: bean name to bean instance. */
// 单例bean缓存 beanName ---> bean instance
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
// bean工厂缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
// '早期'bean 缓存,此缓存中的bean不是完整的,在bean创建过程中,就已经放入此缓存中了.提早曝光bean。未进行属性填充和初始化。
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

二级缓存

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
// 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.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 提前将创建的bean实例加入到singletonFactories中
// 这里是为了后期避免循环依赖
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}


/**
* Add the given singleton factory for building the specified singleton
* if necessary.
* <p>To be called for eager registration of singletons, e.g. to be able to
* resolve circular references.
* @param beanName the name of the bean
* @param singletonFactory the factory for the singleton object
*/
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);
}
}
}

  • 这段代码在createBeanInstance(...)方法之后,此时已经创建完毕(在堆中开辟了空间)

一级缓存

添加至一级缓存,同时从二级、三级缓存中删除。

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
/**
* Add the given singleton object to the singleton cache of this factory.
* <p>To be called for eager registration of singletons.
* @param beanName the name of the bean
* @param singletonObject the singleton object
*/
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);
}
}

/**
* Return the (raw) singleton object registered under the given name,
* creating and registering a new one if none registered yet.
* @param beanName the name of the bean
* @param singletonFactory the ObjectFactory to lazily create the singleton
* with, if necessary
* @return the registered singleton object
*/
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 ) {
...
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (Exception e){
....
} finally {
....
}
if (newSingleton) {
addSingleton(beanName,singletonObject);
}
}
}
return singletonObject;

}

注意: 这个getSingleton和上边的getSingleton不同!

不得不说,处理的很是巧妙…..

将jar推到mvn公有库
application中的bean加载
  1. 1. spring循环依赖问题
    1. 1.1. 循环依赖问题的产生
    2. 1.2. spring中的解决方案
    3. 1.3. 各级缓存的值及设置
      1. 1.3.1. 三级缓存
      2. 1.3.2. 二级缓存
      3. 1.3.3. 一级缓存
© 2023 haoxp
Hexo theme