1. Spring中bean的生命周期

  • 构造器创建bean对象
  • 依赖注入
  • init方法初始化bean对象
  • 使用
  • 销毁

2. Spring循环依赖是怎么回事

循环依赖发生在单例对象A的创建过程中(第一步和第二步)需要其他的单例对象B,而这个单例对象B恰好也需要A。循环依赖主要分两种:构造器循环依赖属性循环依赖

3. 如和解决循环依赖

Spring通过三级缓存可以解决属性循环依赖,三级缓存主要如下:

1
2
3
4
5
6
7
8
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
  • singletonObjects: 第一级缓存,存放完整可用的单例对象

  • earlySingletonObjects: 第二级缓存,存放提前曝光的单例对象

  • singletonFactories: 第三级缓存,存放单例对象的工厂

那么三级缓存如何解决属性循环依赖的呢?看一下单例bean的创建过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 != NULL_OBJECT ? singletonObject : null);
}

为什么三级缓存可以解决循环依赖呢?这是因为在bean生命周期的第一步结束后,会将该对象放入三级缓存。这也是无法解决构造器循环依赖的原因。

1
2
3
4
5
6
7
8
9
10
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);
}
}
}

https://blog.csdn.net/u010853261/article/details/77940767