循环依赖

循环依赖

Spring 内部维护了三个 Map,也就是常说的三级缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** Cache of singleton objects: bean name to bean instance. */
// 常说的第一级缓存
// 存储的是所有创建好了的单例 Bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
// 常说的第三级缓存
// 提前暴露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
// 第二级缓存
// 完成实例化,但是还未进行属性注入及初始化的对象
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

循环依赖分为有 AOP 的循环依赖,和没有 AOP 的循环依赖

Spring 解决循环依赖是有前置条件的

  • 出现循环依赖的 Bean 必须要是 单例
  • 依赖注入的方式不能 全是构造器注入 的方式
    • A 中注入 B 的方式为 setter 方法,B 中注入 A 的方式为构造器,这种情况能被解决
    • B 中注入 A 的方式为 setter 方法,A 中注入 B 的方式为构造器,这种情况不能被解决
      • 在创建 Bean 的时候默认是按照 自然排序 来进行创建的,所以第一步 Spring 会去创建 A

步骤

创建 Bean 的过程中分为 三步

  • 实例化
    • AbstractAutowireCapableBeanFactory 中的 createBean 方法,即 createBeanInstance 方法
  • 属性注入
    • AbstractAutowireCapableBeanFactorypopulateBean 方法
  • 初始化
    • AbstractAutowireCapableBeanFactoryinitializeBean 方法

getBean( A )doGetBean 方法开始

1
2
3
4
// AbstractBeanFactory
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

doGetBean

尝试 从缓存中获取,若获取不到,就创建

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
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// ...
// 这里先尝试从缓存中获取,若获取不到,就走下面的创建
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// ...
}
else {
// ...
try {
// ...
// 如果是 singleton
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建 Bean 的核心方法
return createBean(beanName, mbd, args);
}
// ...
});
// ...
}
// 如果是 prototype
// ...
}
// ...
}
// ...
return (T) bean;
}

从缓存尝试拿A

首先到缓存中尝试去获取 Bean( A ),即 getSingleton(beanName, true)

1
2
3
4
5
Object sharedInstance = getSingleton(beanName);

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

调用 getSingleton( 从缓存 ) 方法

1
2
3
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 省略...因为第一次来缓存里肯定没 A
}

但是第一次来缓存里肯定没有 A,就会走下面的 getSingleton(beanName, singletonFactory) 方法

  • 因为 二参 是匿名函数,即 lambda,到 getSingleton 调用它的时候才执行
1
2
3
4
5
6
7
8
9
10
11
12
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
// lambda
try {
// 在 getSingleton 里面调用 createBean 方法,即 doCreateBean
// 即 createBeanInstance
return createBean(beanName, mbd, args);
}
// ...
});
// ...
}

getSingleton( 从创建拿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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// ...
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// logger...
// ...
try {
// 执行匿名函数,即执行 createBean,即执行 doCreateBean
// 即 createBeanInstance
singletonObject = singletonFactory.getObject();
newSingleton = true;
}

// ...
// 下半部分先不看

// 当 A 完成实例化,完成对 B 的属性注入后
// 加入到一级缓存中
// if (newSingleton) {
// addSingleton(beanName, singletonObject);
// }
}
}
}

执行匿名函数,先执行 createBean,即执行 doCreateBean

  • 执行 createBeanInstance 拿到 Bean( A ) 实例后
  • 看到 earlySingletonExposuretrue
  • 然后就会执行 addSingletonFactory,把 新的 Bean 实例( A ) 包装成工厂,添加到 三级缓存 singletonFactory
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
// AbstractAutowireCapableBeanFactory
protected Object doCreateBean(
final String beanName, final RootBeanDefinition mbd,
final @Nullable Object[] args)
throws BeanCreationException {
// ...
if (instanceWrapper == null) {
// 实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
// ...
// earlySingletonExposure
boolean earlySingletonExposure = (mbd.isSingleton()
&& this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// logger...
// 把新的 Bean 实例( A )包装成工厂,添加到三级缓存 singletonFactory
// 在没有 AOP 的情况下,getEarlyBeanReference 返回的工厂里面的还是现在的 Bean 实例( A )
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// ...
Object exposedObject = bean;
try {
// 属性赋值
populateBean(beanName, mbd, instanceWrapper);

// 就此打住,不看下面
// 初始化
// exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// ...

return exposedObject;
}
  • 重点是

    • earlySingletonExposuretrue

    • 然后执行了 addSingletonFactory,把 新的 Bean 实例( A )包装成工厂添加到三级缓存 singletonFactory

    • addSingletonFactory 的二参是匿名函数,里面是 getEarlyBeanReference

      • 注意:在 没有 AOP!!! 的情况下,getEarlyBeanReference 返回的工厂还是现在的 Bean 实例( A )
    • ```java
      // 二参是匿名函数
      // 在没有 AOP 的情况下,getEarlyBeanReference 返回工厂的还是现在的 Bean 实例
      protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
      // Assert..
      synchronized (this.singletonObjects) {
      // 此时 A 实例化了,但还没完成初始化
      // 所以一级缓存单例池 singletonObjects 里面害没有 A
      if (!this.singletonObjects.containsKey(beanName)) {
      // 将 A 的工厂加入到三级缓存
      this.singletonFactories.put(beanName, singletonFactory);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
      }
      }
      }

      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

      然后 `doCreateBean` 还没完,还有 `populateBean` 属性注入

      - 就会发现 A 里面还有个 B,然后 `getBean(B)`,**开始套壳了!!**

      ```java
      // AbstractAutowireCapableBeanFactory
      protected Object doCreateBean(
      final String beanName, final RootBeanDefinition mbd,
      final @Nullable Object[] args)
      throws BeanCreationException {

      // 实例化

      // addSingletonFactory 加入三级缓存

      Object exposedObject = bean;
      try {
      // 属性赋值,会发现 B,然后 getBean(B)
      populateBean(beanName, mbd, instanceWrapper);

      // 就此打住,先不看下面
      // 初始化
      // exposedObject = initializeBean(beanName, exposedObject, mbd);
      }
      // ...

      return exposedObject;
      }

套壳开始(A拿B)

getBean(B) -> doGetBean

还是先执行 getSingleton( 从缓存获取 ),发现 B 没实例化

然后 createBean

1
2
3
4
5
6
7
8
9
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建 Bean 的核心方法
return createBean(beanName, mbd, args);
}
});
// ...
}

createBeandoCreateBean

  • createBeanInstance 创建 B 实例
  • 然后执行 addSingletonFactory 加入三级缓存
1
2
3
4
5
6
7
if (earlySingletonExposure) {
// logger...

// 把新的 Bean 实例( B )包装成工厂,添加到三级缓存 singletonFactory
// 在没有 AOP 的情况下,getEarlyBeanReference 返回的工厂里面的还是现在的 Bean 实例( B )
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

然后属性注入,发现 有个 A

然后 getBean( A )

又套壳(B拿A,成功了)

又回到 doGetBean 中的 getSingleton( 从缓存中获取 )

但是这次发现 A 就在三级缓存中!!!

  • 拿到 A
  • 把 A 放进 二级缓存 earlySingletonObjects 中( 表示 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
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 单例池还没有 A,没完成属性注入呢,还在等 B
Object singletonObject = this.singletonObjects.get(beanName);
// 进入
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 二级缓存也没有
singletonObject = this.earlySingletonObjects.get(beanName);
// 进入
if (singletonObject == null && allowEarlyReference) {
// 这时候发现,三级缓存里有 A 包装而成的工厂
// ( 其实在没有 AOP 的情况下,这个工厂还是 A )
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// 拿到了,不为 null
if (singletonFactory != null) {
// 拿到 A
singletonObject = singletonFactory.getObject();
// 把 A 放进二级缓存 earlySingletonObjects 中
// 表示 A 还未完全初始化,注意未完全!!
this.earlySingletonObjects.put(beanName, singletonObject);
// 然后把 A 从三级缓存拿掉
this.singletonFactories.remove(beanName);
}
}
}
}
// 把 A 返回
return singletonObject;
}

拿到 A 了,就直接返回,然后 B 完成属性注入,完成初始化

为什么 B 拿到的是 半残 的 A,但是没出问题?

  • 因为 B 拿的是 A 的 引用,之后 B 完成初始化还得回传给 A

回到A拿B

B 完成初始化后,回到 A 拿 B 的时候的 getSingleton

  • 当 B 完成实例化,即完成对 A 的属性注入后
    • 把 B 加入到 一级缓存 中,即 单例池
    • 把 B 从 三级缓存工厂移除
    • 把 B 从 二级工厂 移除
  • 这标志着 B 彻底完成初始化!
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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// ...
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {

// logger...

// ...
try {
// 执行匿名函数,即执行 createBean,即执行 doCreateBean
// 即 createBeanInstance
// 这句执行完,表明 B 完成实例化,即完成 B 对 A 的属性注入,初始化
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
// ...
// 当 B 完成实例化,即完成 B 的属性注入后
// 把 B 加入到一级缓存中、从三级缓存工厂中移除、从二级工厂移除
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
}
}

// 把 B 加入到一级缓存中,即单例池
// 把 B 从三级缓存工厂中移除
// 把 B 从二级工厂移除
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);
}
}

A 完成属性注入,完成初始化

回到我们拿A

回到我们自己( 容器 )拿 A 的时候,getSingleton

  • 当 A 完成实例化,即完成对 B 的属性注入后
    • 把 A 加入到一级缓存中,即单例池
    • 把 A 从三级缓存工厂中移除
    • 把 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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// ...
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// logger...
// ...
try {
// 执行匿名函数,即执行 createBean,即执行 doCreateBean
// 即 createBeanInstance
// 这句执行完,表明 A 完成实例化,即完成 A 对 B 的属性注入,初始化
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
// ...
// 当 A 完成实例化,即完成 A 的属性注入后
// 把 A 加入到一级缓存中、从三级缓存工厂中移除、从二级工厂移除
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
}
}

// 把 A 加入到一级缓存中,即单例池
// 把 A 从三级缓存工厂中移除
// 把 A 从二级工厂移除
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);
}
}

结束!!

getEarlyBeanReference

这里就是上面说到,即将注入到 B 中的 A 是通过 getEarlyBeanReference 方法 提前暴露 出去的一个工厂对象,还不是一个完整的 Bean

1
2
3
4
5
6
7
8
9
10
11
12
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}

getEarlyBeanReference 方法实际上就是调用了后置处理器的 getEarlyBeanReference 方法,而真正实现了这个方法的后置处理器只有一个,就是通过 @EnableAspectJAutoProxy 注解导入的 AnnotationAwareAspectJAutoProxyCreator

也就是说如果在不考虑 AOP 的情况下,上面的代码等价于

1
2
3
4
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
return exposedObject;
}

也就是说这个工厂啥都没干,直接将实例化阶段创建的对象返回了

在没 AOP 的情况下,三级缓存没毛用

在有 AOP 的情况下,getEarlyBeanReference 生成的工厂是经过包装的,不再是原来那个 A 或 B 了,因为 AOP 了

摘自大佬的一张图:

循环依赖