Spring中的bean存在循环嵌套依赖的情况就叫做循环依赖
如下图:
@Component
public class A {
@Autowired
private B b;
......
}
@Component
public class B {
@Autowired
private A a;
......
}
Spring循环依赖出现在创建bean时,首先调用AbstractBeanFactory#getBean()方法获取bean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 根据beanName尝试从三级缓存中获取bean实例
Object sharedInstance = getSingleton(beanName);
// 当三级缓存中存在此bean,表示当前该bean已创建完成 || 正在创建
if (sharedInstance != null && args == null) {
// 返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
// 如果sharedInstance是普通的单例bean,下面的方法会直接返回,但如果sharedInstance是FactoryBean类型的,
// 则需要调用getObject工厂方法获取bean实例,如果用户想获取FactoryBean本身,这里也不会做特别的处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 当bean还未创建
else {
// 这一大段代码省略
......
// 正式开始创建bean实例
if (mbd.isSingleton()) { // 当该bean的scope为singleton或者为空时
sharedInstance = getSingleton(beanName, () -> { // 从三级缓存中获取bean实例
try {
return createBean(beanName, mbd, args); // 真正创建bean
}
catch (BeansException ex) {
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
// 创建bean的后续处理
......
return (T) bean;
}
/**
* 尝试从三级缓存中获取bean实例
*
* 从一级缓存(单例池) -> 二级缓存 -> 三级缓存依次获取,当三级缓存中都不存在bean实例时,那个该bean处于还未创建的状态
*
* 这里解释一下三级缓存分别的作用
*/
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 尝试从三级缓存中获取bean实例
Object singletonObject = this.singletonObjects.get(beanName); // 从一级缓存中获取bean
// 如果一级缓存中不存在该bean实例 && 该bean正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // isSingletonCurrentlyInCreation(beanName)判断这个bean是否在创建过程中,对象是否有循环依赖
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName); // 尝试从二级缓存中获取提前曝光的bean实例
// 如果二级缓存中不存在giantbean实例 && 允许从singletonFactories从获取bean实例
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); // 从三级缓存中获取bean实例
// 如果bean存在,将该bean实例从三级缓存升级到二级缓存中提前曝光bean实例,并且从三级缓存中删除
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
// 这一大段代码省略
......
// 实例化bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
// 这一大段代码省略
......
// 创建bean实例转化成BeanWrapper对象
if (instanceWrapper == null) {
// 调用bean的构造方法进行初始化,经过这一步,bean属性并没有被赋值,只是一个空壳,这是bean初始化的【早期对象】
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
......
// 判断bean是否存在循环依赖
// 如果当前bean是单例,且支持循环依赖,且当前bean正在创建,通过往singletonFactories添加一个objectFactory,这样后期如果有其他bean依赖该bean 可以从singletonFactories获取到bean
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 添加工厂对象到singletonFactories缓存中,【提前暴露早期对象】
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 给已经已经初始化的属性赋值,包括完成bean的依赖注入
populateBean(beanName, mbd, instanceWrapper);
......
return exposedObject;
}
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 这一大段代码省略
......
// 为属性赋值
applyPropertyValues(beanName, mbd, bw, pvs);
}
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// 这一大段代码省略
......
// 为当前bean中属性赋值,包括依赖注入的属性
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
// 这一大段代码省略
......
}
/**
* 如果当前初始化的bean有属性需要注入的,将会调用resolveReference(argName, ref)来返回需要注入的bean
*/
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
// 获取需要依赖注入属性的值
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
// 这一大段代码省略
......
}
/**
* 在该方法中,会为当前初始化bean主要为属性注入另外一个bean,调用getBean()方法获取需要注入的bean,最终注入到属性中
*/
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
Object bean;
String refName = ref.getBeanName();
refName = String.valueOf(doEvaluate(refName));
if (ref.isToParent()) {
if (this.beanFactory.getParentBeanFactory() == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Can't resolve reference to bean '" + refName +
"' in parent factory: no parent factory available");
}
bean = this.beanFactory.getParentBeanFactory().getBean(refName);
}
else {
// 当前初始化bean主要为属性注入另外一个bean,调用getBean()方法获取需要注入的bean,最终注入到属性中
bean = this.beanFactory.getBean(refName);
this.beanFactory.registerDependentBean(refName, this.beanName);
}
if (bean instanceof NullBean) {
bean = null;
}
return bean;
}
catch (BeansException ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
}
}
调用getBean()
方法又回到了开头的getBean(beanName)
,此时去实例化B,实例化B的时候一步执行刚才实例bean A的步骤,然后到了调用populateBean(beanName, mbd, instanceWrapper)
方法注入bean A,又回到第二次实例化bean A,在调用getSingleton(beanName)
方法尝试从三级缓存中获取bean实例时,从第三级缓存singletonFactories
中获取到正在创建的bean A,这样就获取到bean A了,然后返回给bean B注入到bean B的属性中,完成bean B的初始化了,最后返回给bean A注入到bean A的属性中,这样就完成了循环依赖了。初始化bean A和bean B的流程图如下: