写点什么

【源码系列】Spring Bean 循环依赖

用户头像
Alex🐒
关注
发布于: 2021 年 06 月 09 日

Spring Bean 默认在单例的情况下支持循环依赖(属性注入)。如下代码启动执行不会异常:

@Configuration@ComponentScan("com.alex.space")public class AppConfig {
}
@Componentpublic class A { @Autowired B b;
public A() { System.out.println("constructor from A"); }}
@Componentpublic class B { @Autowired A a;
public B() { System.out.println("constructor from B"); }}
public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
System.out.println("========"); System.out.println(ctx.getBean(A.class)); System.out.println(ctx.getBean(B.class));}
复制代码


输出结果

constructor from Aconstructor from B========com.alex.space.A@247bddadcom.alex.space.B@d35dea7
复制代码


如果要关闭循环依赖

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.setAllowCircularReferences(false);// 为什么要这么写?可以看 AnnotationConfigApplicationContext 的构造方法ctx.register(AppConfig.class);ctx.refresh();
// 会出现如下异常// Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?
复制代码


要了解 Spring 是如何解决循环依赖的问题,先要了解 Spring Bean 的构造过程以及生命周期。

Spring Bean 生命周期

Spring 容器创建后初始化的的大概描述,包括容器的创建:

  1. 实例化 ApplicationContext

  2. 注册配置类,解析配置类的 BeanDefinition 加入 BeanDefinitionMap

  3. 完成 Bean 的扫描,解析所有 BeanDefinition,加入 BeanDefinitionMap

  4. 实例化 Bean 流程


Spring 容器的初始化以及 Bean 的实例化/自动注入是在上面例子中的 register()refresh() 方法中完成的

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {  // 【1】实例化 ApplicationContext,创建 BeanFactory,解析 Spring 自身的 Bean,加入 BeanDefinitionMap  this();  // 【2】注册配置类,即 AppConfig 的 BeanDefinition,加入 BeanDefinitionMap  register(annotatedClasses);  refresh();}
// 初始化 Spring 容器和 Beanpublic void refresh() throws BeansException, IllegalStateException { // 初始化当前的 Context 对象、BeanFactory,以及一些准备工作,扫描出 BeanDefinitionMap prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory);
try { // 【3】完成 Bean 的扫描,A/B 的 BeanDefinition,加入 BeanDefinitionMap // 这里使用的是 ConfigurationClassPostProcessor(后置处理器)#processConfigBeanDefinitions invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor、国际化、事件分发等等方法
// 开始实例化单例的 Bean,不包含懒加载的 finishBeanFactoryInitialization(beanFactory);
} catch (BeansException ex) { // 销毁已经创建的单例 Bean destroyBeans(); }}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // ... // 【4】实例化 Bean 流程的入口 beanFactory.preInstantiateSingletons();}
复制代码

Spring Bean 实例化

实例化 Bean 的大致流程:

  1. 遍历所有扫描出来的 BeanDefinition,进行验证:是否 Lazy、是否 prototype、是否 abstract 等等

  2. 对 dependsOn 进行一些特殊处理,递归的实例化依赖的 bean

  3. 实例化 Bean

  4. 执行属性注入

  5. 执行 Bean 初始化

  6. 初始化完成,加入单例池

  7. 注册 DisposableBean(销毁 Bean 时回调方法)


在进入源码前,先看看几个概念

什么是 BeanDefinition

描述一个 Bean 实例(Instance)的各种属性,如:bean class、scope、lazyInit、dependsOn,isSingleton、isAbstract...,允许 bean factory 后置处理器,对 bean property 和其他元数据进行修改。实现类:


AbstractBeanDefinition 实现了大部分的方法,子类 AnnotatedBeanDefinition 可以获取注解信息。

什么是 MergedBeanDefinition

一个合并了 BeanDefinition 和 Parent BeanDefinition 的对象(递归处理),最终以 RootBeanDefinition 的类型存在。创建 Bean 的时候使用的都是 MergedBeanDefinition(mbd)。在 Bean 的创建过程中,有多种后置处理器(例如: MergedBeanDefinitionPostProcessor)进行扩展处理。

BeanFactory vs FactoryBean

BeanFactory 给具体的 IOC 容器的实现提供了规范,实现 BeanFactory 接口的类,表明此类是一个工厂,作用就是配置、新建、管理各种 Bean,例如:ApplicationContextDefaultListableBeanFactoryAbstractAutowireCapableBeanFactory


FactoryBean 是一种 Bean 类型,Spring 中有两种类型的 Bean,一种是普通 Bean,另一种是 FactoryBean,FactoryBean 提供 getObject() 方法返回 Bean,即通过将复杂的实例化 Bean 的逻辑封装到 FactoryBean 中由上层使用。

开始 Bean 的实例化

开始 Bean 的实例化,进入 beanFactory.preInstantiateSingletons(); 方法查看(DefaultListableBeanFactory

public void preInstantiateSingletons() throws BeansException {  // 循环便利所有扫描出的 beanName  List<String> beanNames = new ArrayList(this.beanDefinitionNames);  for (String beanName : beanNames) {    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);    // 【1】过滤所有不符合条件的 beanDefinition,懒加载、非单例、抽象类    if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {      if (!isFactoryBean(beanName)) {        // 实例化 Bean 方法        getBean(beanName);      }    }  }}
public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false);}
复制代码


getBean() 方法最终会进入 AbstractBeanFactory#doGetBean(),实例化 Bean 的前置流程,通过流程图对照源码


代码解析

protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) {  /*   * 获取 name 对应的真正 beanName,传入的参数可以是 alias,也可能是 FactoryBean name,需要进行解析,包含以下内容:   * 1. 如果是 FactoryBean,则去掉修饰符 “&”   * 2. 沿着引用链获取 alias 对应的最终 name   */   String beanName = this.transformedBeanName(name);    // 核心方法:从单例池中获取 bean,第一次 get 是 null,引申出两个问题:  // 1. 创建 bean 的时候,为什么要 get  // 2. bean 正在实例化,为什么要从缓存池中拿 bean  // 【推断】一个 bean 的实例化过程有可能进入超过一次  Object sharedInstance = this.getSingleton(beanName);  Object bean;  if (sharedInstance != null && args == null) {    // 第一次不会进入这个分支    // 如果实例已经存在,返回实例    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);  } else {    BeanFactory parentBeanFactory = this.getParentBeanFactory();    // 如果当前 bean 不在当前的 BeanFactory 中,从 Parent BeanFactory 中查找...        try {      // 将 GenericBeanDefinition 转换成 RootBeanDefinition(MergedBeanDefinition)      RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);            // 【2】进行一些验证,包括 dependsOn 的处理(控制 bean 的实例化顺序,递归的实例化依赖的 bean)
if (mbd.isSingleton()) { // 如果 bean 是单例的,实例化 bean,这里是【核心方法】 sharedInstance = this.getSingleton(beanName, () -> { try { // 【3】实例化 Bean return this.createBean(beanName, mbd, args); } catch (BeansException var5) { // 失败的话,从缓存中移除,并执行 destory this.destroySingleton(beanName); throw var5; } }); // 返回实例 bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else { // Scope:Prototype... bean的处理逻辑 } } catch (BeansException var26) { throw var26; } } // 类型检查和转换...}
复制代码

Bean 缓存

Spring 中与 Bean 相关的缓存有三个

// 单例池,包含所有实例化完成的 Beanprivate final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 缓存 bean name -> ObjectFactory 的关系,ObjectFactory 创建对应的 beanprivate final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 正在实例化的 bean,与单例池互斥private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
复制代码


第一个 getSingleton(),表示缓存中获取 Bean 对象,Bean 第一次实例化会返回 null。

public Object getSingleton(String beanName) {    // 第二个参数表示允许早期依赖      return getSingleton(beanName, true);}
protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 先检查单例池 Object singletonObject = this.singletonObjects.get(beanName); // 重点是第二个判断,如果 bean 正在创建中 // 在后面的方法中能看到,在 bean 第一次创建时,bean name 放入了 singletonsCurrentlyInCreation // 当 bean 第二次调用方法时,进入 if 逻辑 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { singletonObject = this.earlySingletonObjects.get(beanName); // 如果 earlySingletonObjects 还没有 bean ,但是允许 allowEarlyReference // 也就是提前暴露了 ObjectFactory,可通过 ObjectFactory 创建 bean 对象 if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // bean 对象创建,并且加入 earlySingletonObjects,ObjectFactory 清除 singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } return singletonObject;}
复制代码


第二个 getSingleton(),同样涉及几个重要的数据结构

// bean 第一次初始化开始阶段,加入 Setprivate final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap(16));
// singletonFactory 就是 () => { this.createBean(...);}public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Map var3 = this.singletonObjects; synchronized(this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { // 第一次实例化,获取不到对象 // 加入 singletonsCurrentlyInCreation,表示 bean 开始(正在)实例化过程中 this.beforeSingletonCreation(beanName);
boolean newSingleton = false; try { // 通过 ObjectFactory 创建 bean,() => { this.createBean(...);} singletonObject = singletonFactory.getObject(); newSingleton = true; } catch(Exception e) { // ... } finally { // 从 singletonsCurrentlyInCreation 移除,表示实例化完成 this.afterSingletonCreation(beanName); } if (newSingleton) { // 【6】加入单例池 singletonObjects,移除其他缓存 this.addSingleton(beanName, singletonObject); } } return singletonObject; }}
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); }}
复制代码


一个无循环依赖的 Bean 的实例化过程中,缓存的使用(earlySingletonObjects 没有用到 )过程:

创建 Bean

回到 createBean() 方法(AbstractAutowireCapableBeanFactory),此处时创建 bean 的真正逻辑,会有多处 Bean 扩展点调用

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) {  RootBeanDefinition mbdToUse = mbd;  // 解析 Bean Class  Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);  if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {    mbdToUse = new RootBeanDefinition(mbd);    mbdToUse.setBeanClass(resolvedClass);  }
// 对 override 属性进行标记和验证 mbdToUse.prepareMethodOverrides();
Object beanInstance; // 【后置处理器调用 1】InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
// 创建 Bean beanInstance = this.doCreateBean(beanName, mbdToUse, args); return beanInstance;}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) { BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); }
// 实例化 Bean 的 Java 对象,属性还没有注入 if (instanceWrapper == null) { // 【后置处理器调用 2】SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors instanceWrapper = this.createBeanInstance(beanName, mbd, args); }
Object bean = instanceWrapper.getWrappedInstance(); synchronized(mbd.postProcessingLock) { // 【后置处理器调用 3】MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); }
// 【重点关注】判断是否允许循环依赖 // 默认允许单例循环依赖 allowCircularReferences 属性值,修改这个属性可以改变 Spring 不允许循环依赖 boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName); if (earlySingletonExposure) { // 当前 bean 正在实例化的过程中,将对应的 ObjectFactory 加入工厂集合 singletonFactories 中 // lambda 表示 ObjectFactory,返回 bean(mbd),添加了扩展点 // 提前暴露了 ObjectFactory 即当前未实例化完成的 bean this.addSingletonFactory(beanName, () -> { // 【后置处理器调用 4】SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference // 【知识点】此处提前做了 AOP 代理 return this.getEarlyBeanReference(beanName, mbd, bean); }); }
Object exposedObject = bean; try { // 【4】填充属性(注入) this.populateBean(beanName, mbd, instanceWrapper); // 【5】Bean初始化 exposedObject = this.initializeBean(beanName, exposedObject, mbd); } catch (Throwable var18) { // ... }
// 再次基于依赖关系验证循环依赖的 bean 是否都已经实例化
// 【7】注册 DisposableBean,在销毁对应的 bean 时能够回调 destroy 方法 this.registerDisposableBeanIfNecessary(beanName, bean, mbd); return exposedObject;}
复制代码


addSingletonFactory() 方法,ObjectFactory 加入 singletonFactories,并且从 earlySingletonObjects 中移除

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {    synchronized (this.singletonObjects) {      if (!this.singletonObjects.containsKey(beanName)) {        this.singletonFactories.put(beanName, singletonFactory);        this.earlySingletonObjects.remove(beanName);        this.registeredSingletons.add(beanName);      }    }}
复制代码
Bean 后置处理器

后置处理器对所有的 Bean 都生效,需要自己实现筛选逻辑,上面遇到的几个后置处理器

  • InstantiationAwareBeanPostProcessor

  • postProcessBeforeInstantiation,bean 实例化前调用,是对 bean 定义进行修改【后置处理器调用 1】

  • postProcessAfterInstantiation,bean 实例化后调用,在属性注入之前【后置处理器调用 5】

  • postProcessProperties,在将属性注入 bean 实例前调用,对属性值修改【后置处理器调用 6】

  • MergedBeanDefinitionPostProcessor

  • postProcessMergedBeanDefinition,对 MergedBeanDefinition 进行处理,在属性注入之前【后置处理器调用 3】

  • Spring 自身实现 AutowiredAnnotationBeanPostProcessor,解析 @Autowired@Value@Inject 用于后续的属性填充

  • SmartInstantiationAwareBeanPostProcessor

  • determineCandidateConstructors,解析 Bean 类里构造函数上的 @Autowired 注解,推断构造器,【后置处理器调用 2】

  • getEarlyBeanReference,AOP 代理【后置处理器调用 4】

实例化 Bean

通过工厂方法或构造函数创建,需要根据参数推断构造函数,否则使用默认构造函数

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {    // 如果工厂方法不为空,则使用工厂方法进行实例化    if (mbd.getFactoryMethodName() != null) {      return instantiateUsingFactoryMethod(beanName, mbd, args);    }      // 推断构造函数,利用构造函数进行实例化...      // 1. 使用特定构造函数注入    return autowireConstructor(beanName, mbd, null, null);
// 2. 默认构造函数 return instantiateBean(beanName, mbd);}
复制代码

属性注入

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {    // 【后置处理器调用 5】InstantiationAwareBeanPostProcessors#postProcessAfterInstantiation
if (!continueWithPropertyPopulation) { // 如果后置处理器处理完,指明不需要执行后续的属性注入过程,则退出方法 return; } // 获取 bean 的属性值集合 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// autowire by name or autowire by type if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // autowire by name if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // autowire by type if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; }
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; // 【后置处理器调用 6】InstantiationAwareBeanPostProcessors#postProcessProperties if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // AutowiredAnnotationBeanPostProcessor 处理 @Autowired // CommonAnnotationBeanPostProcessor 处理 @Resource // ImportAwareBeanPostProcessor 处理 @Import // 【此处会调用 CreateBean】 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } // 检查依赖 // 【执行属性注入】 applyPropertyValues(beanName, mbd, bw, pvs);}
复制代码
循环依赖

回到开头的例子,在 Create A 时,在属性注入 A 的时候,会开始 Create B 的流程,在熟悉注入 B 的时候,又调用 Create A 的流程,逻辑就回到了刚才的 getSingleton() 方法。

// beanA 第二次进入protected Object getSingleton(String beanName, boolean allowEarlyReference) {    // 还没有单例实例    Object singletonObject = this.singletonObjects.get(beanName);    // A 正在创建    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {      synchronized (this.singletonObjects) {        // earlySingletonObjects 此时还没有(文章最后有流程图)        singletonObject = this.earlySingletonObjects.get(beanName);        // 允许提前暴露,此时 A -> ObjectFactory 存在        if (singletonObject == null && allowEarlyReference) {          ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);          // 通过 ObjectFactory 获取 A          if (singletonFactory != null) {            singletonObject = singletonFactory.getObject();            // earlySingletonObjects 存入 A            this.earlySingletonObjects.put(beanName, singletonObject);            // 移除 ObjectFactory            this.singletonFactories.remove(beanName);          }        }      }    }    return singletonObject;  }
复制代码


在回到调用 getSingleton() 方法的地方,返回 A 的 Bean 对象(目前还没有实例化完成),注入到 B 中

Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {      // 返回 Bean 实例(可能是未完成实例化的)      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}
复制代码
autowire

autowireByName 基于 beanName 获取依赖的 bean,并将依赖关系保存在对应的集合中,如果依赖的 bean 未被实例化则需要执行实例化逻辑:

protected void autowireByName(      String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { // 依赖的 Bean 执行 getBean -> doGetBean Object bean = getBean(propertyName); // 添加到属性集合 pvs.add(propertyName, bean); // 记录依赖关系 registerDependentBean(propertyName, beanName); } }}
public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false);}
复制代码


autowireByType 相比于 autowireByName 多了一个类型推断过程,但是整体流程是相同的,依赖的 bean 未被实例化则需要执行实例化。

属性注入

将 bean 的所有属性全部注入到 bean 实例中,之前虽然已经创建了实例,但是属性仍然存在于 beanDefinition 实例中,applyPropertyValues 会将相应属性转换成 bean 中对应属性的真实类型注入到对应属性上:

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {    // 属性类型转换的过程...      // 设置到 beanWrapper    bw.setPropertyValues(new MutablePropertyValues(deepCopy));}
复制代码

Bean 初始化

完成了属性注入,接下来容器会执行初始化方法,主要包含 4 个步骤:

  1. 调用所有 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 接口方法

  2. BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 是 Spring 将数据暴露出去的一种方式,我们在自己的 bean 集成并实现对应的接口方法,会在此处被调用。

  3. 后置处理器 postProcessBeforeInitialization 调用,这里会执行 @PostConstruct 注解方法

  4. 执行初始化方法,InitializingBean 接口方法调用和 initMethod 方法调用

  5. 后置处理器 postProcessAfterInitialization 调用


protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {    // 调用所有 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 接口方法    invokeAwareMethods(beanName, bean);
// 【后置处理器调用 7】BeanPostProcessor#postProcessBeforeInitialization Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); }
// 执行初始化方法 invokeInitMethods(beanName, wrappedBean, mbd); // 【后置处理器调用 8】BeanPostProcessor#postProcessAfterInitialization if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }
return wrappedBean;}
复制代码
初始化方法

初始化方法的调用顺序,@PostConstruct 注解方法最先调用,然后调用 InitializingBean 接口方法,然后反射调用 init-method(如果 XML 中设置)

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) {      // 如果 bean 继承了 InitializingBean 接口,优先调用 InitializingBean#afterPropertiesSet      boolean isInitializingBean = (bean instanceof InitializingBean);      if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {          ((InitializingBean) bean).afterPropertiesSet();      }
// 如果设置了 initMethod 方法,并且这个类不是 InitializingBean 类型,并且方法名不是 afterPropertiesSet String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); }}
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) { String initMethodName = mbd.getInitMethodName(); final Method initMethod = (mbd.isNonPublicAccessAllowed() ? BeanUtils.findMethod(bean.getClass(), initMethodName) : ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName)); // 反射调用 ReflectionUtils.makeAccessible(initMethod); initMethod.invoke(bean);}
复制代码

Bean 缓存的问题

刚刚提到与 Bean 相关的缓存有三个,通过 getSingleton() 方法逻辑可以看到其实是三级缓存


  • singletonObjects 是第一级缓存,存储实例化好的单例 Bean

  • singletonFactories 是第二级缓存,存储正在实例化的 Bean 的 ObjectFactory

  • earlySingletonObjects 是第三级缓存,存储正在实例化的 Bean

为什么要设计三级缓存?

假设改造 getSingleton() 为二级缓存,可以实现同样的功能

protected Object getSingleton(String beanName, boolean allowEarlyReference) {    Object singletonObject = this.singletonObjects.get(beanName);    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {      synchronized (this.singletonObjects) {        if (singletonObject == null && allowEarlyReference) {          ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);          if (singletonFactory != null) {            singletonObject = singletonFactory.getObject();          }        }      }    }    return singletonObject;}
复制代码


为了防止重复创建,ObjectFactory 的代码会非常复杂,如果每次都通过工场创建性能浪费。并且 Bean 是单例的,对象创建出来之后可以在各处引用,不在需要 ObjectFactory。


同时解决了循环引用的 AOP 的问题,通过 ObjectFactory 提前做 AOP 代理,如果是直接返回对象,此时注入的对象还不是代理。

循环依赖

从源码可以看出来,Spring Bean 循环依赖的处理,主要是通过与 Bean 相关的三个缓存来实现的。

单向依赖

A->B,主要流程和缓存的变化

循环依赖

A->B,B->A,主要流程和缓存的变化




发布于: 2021 年 06 月 09 日阅读数: 27
用户头像

Alex🐒

关注

还未添加个人签名 2020.04.30 加入

还未添加个人简介

评论

发布
暂无评论
【源码系列】Spring Bean 循环依赖