Springboot 循环依赖源码解析(getBean源码/refresh中的finishBeanFactoryInitialization)

184 阅读1分钟

1.循环依赖的问题

如果A对象中对象中嵌套B对象,B对象中又嵌套A对象,那么Spring创建对象时,岂不是会陷入循环中

@Component
public class A {
   @Resource //@Resource 是JDK自带的注解
   private B b;
   private String astr = "astr";
}
@Component
public class B {
   private String bstr="bstr";
   @Resource
   private A a;
}

2. 三级缓存

/** 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. */
/** 三级缓存, 缓存objectFactory,一个lambda的表达式 ,在表达式中创建二级缓存对象 
getEarlyBeanReference
 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
/** 二级缓存,存放bean对象的半成品 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
graph TD
getBean --> doGetBean --> createBean --> doCreateBean --> createBeanInstance --> addSingletonFactory --> populateBean --> getBean

910ecc8c78b908bec62159506a8f395.png

3. 源码解析

3.1 finishBeanFactoryInitialization

在refresh方法中有一步非常关键的方法 finishBeanFactoryInitialization ,即初始化bean 具体调用是

// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();

3.2 getBean方法

preInstantiateSingletons循环遍历beanDefinitions,调用getBean,getBean内部调用doGetBean

3.3 createBean

核心方法是createBean,不过是通过getSingleton的模板方法调用createBean()/doCreateBean

// doGetBean方法中...
sharedInstance = getSingleton(beanName, () -> {
   try {
      return createBean(beanName, mbd, args);
   }
   catch (BeansException ex) {
      // Explicitly remove instance from singleton cache: It might have been put there
      // eagerly by the creation process, to allow for circular reference resolution.
      // Also remove any beans that received a temporary reference to the bean.
      destroySingleton(beanName);
      throw ex;
   }
});
// doCreateBean方法中...
//重要步骤1 ,创建bean,不过所有成员都为默认值
if (instanceWrapper == null) {
   instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//重要步骤2,添加三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
//重要步骤3,填充属性,即填充其他bean属性,会调用getbean方法
populateBean(beanName, mbd, instanceWrapper);
//对象初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
//getEarlyBeanReference方法中...
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  for (BeanPostProcessor bp : getBeanPostProcessors()) {
     if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
        SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
        //重要步骤 , 此处判断是否需要使用AOP创建代理对象(当出现循环依赖时才会提前创建aop对象,否则aop对象都是在initializeBean方法中去创建)
        exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
     }
  }
}
return exposedObject;

4. 究极时序图

image.png

5. 参考文献

一文带你简单理解 Spring 循环依赖 - 简书 (jianshu.com)