Spring自问自答系列3循环依赖

编程

我的直觉告诉我循环依赖必定会导致死锁。

但是Spring支持循环依赖,所以本文就来探讨Spring底层是如何实现循环依赖的。

Spring中循环依赖代码的书写

本文Spring的依赖注入通过注解形式实现

A.java

class A {

@Autowired

private B b;

}

B.java

class B {

@Autowired

private A a;

}

第一眼会感觉这依赖不是无限循环下去了吗?

但是想想的确是可行的。

Spring循环依赖的实现

首先需要了解SpringBeanFactory中的一些容器:

缓存

用途

singletonObjects

用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用

earlySingletonObjects

存放原始的 bean 对象(尚未填充属性),用于解决循环依赖

singletonFactories

存放 bean 工厂对象,用于解决循环依赖

singletonsCurrentlyInCreation

存放当前正在创建的bean

循环依赖流程如下:

  1. getBean("a")
  2. 调用第二个getSingleton方法
  3. 发现在singletonFactory里没有A实例,开始实例化A
  4. 执行InstantiationAwareBeanPostProcessor.postProcessPropertyValues注入参数,发现需要B
  5. getBean("b")
  6. 实例化B
  7. 执行InstantiationAwareBeanPostProcessor.postProcessPropertyValues注入参数,发现需要A
  8. getBean("a")
  9. 调用第一个getSingleton方法获取A实例,注入进B实例中的A参数
  10. B实例初始化成功
  11. A实例注入B参数
  12. A实例初始化成功

关键代码

DefaultSingletonBeanRegistry.java中getSingleton(String beanName, boolean allowEarlyReference)方法:

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {

Object singletonObject = this.singletonObjects.get(beanName);

// 判断bean是否正在创建过程中

// 比如A正在初始化过程中需要依赖注入B参数

// Spring就需要区创建B实例,这时候A就在初始化过程中

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();

// earlySingletonObject用来解决循环依赖

this.earlySingletonObjects.put(beanName, singletonObject);

this.singletonFactories.remove(beanName);

}

}

}

}

return (singletonObject != NULL_OBJECT ? singletonObject : null);

}

以上是 Spring自问自答系列3循环依赖 的全部内容, 来源链接: utcz.com/z/511280.html

回到顶部