Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】

接上篇文章:Spring 系列之 Spring 源码笔记:bean 的加载-中【十】

7. 创建 bean

介绍了循环依赖以及 Spring 中的循环依赖的处理方式后,接上篇文章5.2实例化的前置处理继续分析。当经历过 resolveBeforeInstantiation 方法后,程序有两个选择:

  1. 如果创建了代理或者说重写了 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法并在方法 postProcessBeforeInstantiation 中改变了bean,则直接返回就可以了。
  2. 否则需要进行常规的 bean 的创建。而这常规的 bean 的创建就是在 doCreateBean 中完成的。


可以看到代码中总结的步骤非常繁琐,每一步都使用了大量的代码来完成其功能,最复杂也是最难理解的当属循环依赖的处理,在真正进入 doCreateBean 前我们有必要先了解下循环依赖。

7.1 创建 bean 的实例

当我们了解了循环依赖以后就可以深入分析创建 bean 的每一个步骤了,首先我们从 createBeanInstance 开始。
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第1张图片
虽然代码中实例化的细节非常复杂,但是在 createBeanInstance 方法中我们还是可以清晰地看到实例化的逻辑的。

  1. 如果在 RootBeanDefinition 中存在 factoryMethodName 属性,或者说在配置文件中配置了 factory-method,那么 Spring 会尝试使用 instantiateUsingFactoryMethod(beanName, mbd, args) 方法根据 RootBeanDefinition 中的配置生成 bean 的实例。
  2. 解析构造函数并进行构造函数的实例化。因为一个 bean 对应的类中可能会有多个构造函数,而每个构造函数的参数不同,Spring 在根据参数及类型去判断最终会使用哪个构造函数进行实例化。但是,判断的过程是个比较消耗性能的步骤,所以采用缓存机制,如果已经解析过则不需要重复解析而是直接从 RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 缓存的值去取,否则需要再次解析,并将解析的结果添加至 RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 中。

7.1.1 autowireConstructor

对于实例的创建 Spring 中分成了两种情况,一种是通用的实例化,另一种是带有参数的实例化。带有参数的实例化过程相当复杂,因为存在着不确定性,所以在判断对应参数上做了大量工作。

7.1.2 instantiateBean

经历了带有参数的构造函数的实例构造,对于无参构造就太简单了。
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第2张图片

7.1.3 实例化策略

实例化过程中反复提到过实例化策略,那这又是做什么用的呢?其实,经过前面的分析,我们已经得到了足以实例化的所有相关信息,完全可以使用最简单的反射方法直接反射来构造实例对象,但是 Spring 却并没有这么做。
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第3张图片
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第4张图片
程序中,首先判断如果是 beanDefinition.getMethodOverrides() 为空也就是用户没有使用 replace 或者 lookup 的配置方法,那么直接使用反射的方式,简单快捷,但是如果使用了这两个特性,再直接使用反射的方式创建实例就不妥了,因为需要将这两个配置提供的功能切入进去,所以就必须要使用动态代理的方式将包含两个特性所对应的逻辑的拦截增强器设置进去,这样才可以保证在调用方法的时候会被相应的拦截器增强,返回值为包含拦截器的代理实例。

对于拦截器的处理方式非常简单,不再详细介绍。如果感兴趣,会在后面介绍AOP的时候更详细的介绍。

7.2 记录创建 bean 的 ObjectFactory

在 doCreateBean 函数中有这样一段代码:
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第5张图片
经过代码中的分析我们了解变量 earlySingletonExposure 是否是单例、是否允许循环依赖、是否对应的 bean 正在创建的条件的综合。当这 3 个条件都满足时会执行 addSingletonFactory 操作,那么加入 SingletonFactory 的作用是什么?又是在什么时候调用?

之前已经讲过,在解决循环依赖的时候,并不是直接去实例化对象,而是先去监测缓存中是否有已经创建好的对应的 bean,或者是否已经创建好的 ObjectFactory,而此时对于 A 的 ObjectFactory 我们早已创建,所以便不会再去向后执行,而是直接调用 ObjectFactory 去创建 A。这里最关键的是 ObjectFactory 的实现。
在这里插入图片描述
其中 getEarlyBeanReference 的代码如下:
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第6张图片
在 getEarlyBeanReference 函数中并没有太多的逻辑处理,或者说除了后处理器的调用外没有别的处理工作,根据以上分析,基本可以理清 Spring 处理循环依赖的解决办法,在 B 中创建依赖 A 时通过 ObjectFactory 提供的实例化方法来中断 A 中的属性填充,使 B 中持有的 A 仅仅是刚刚初始化并没有填充任何属性的 A,而这正初始化 A 的步骤还是在最开始创建 A 的时候进行的,但是因为 A 与 B 中的 A 所表示的属性地址是一样的,所以在 A 中创建好的属性填充自然可以通过 B 中的 A 获取,这样就解决了循环依赖的问题。

7.3 属性注入

在了解循环依赖的时候,我们曾经反复提到了 populateBean 这个函数,也多少了解了这个函数的主要功能就是属性填充,那么究竟是如何实现填充的呢?
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第7张图片
下面主要介绍在代码注释的四步中的依赖注入和属性填充。

7.3.1 autowireByName

上文提到根据注入类型(byName/byType)提取依赖的 bean,并统一存入 PropertyValues 中,那么我们首先了解下 byName 功能是如何实现的。
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第8张图片

7.3.2 autowireByType

autowireByType 与 autowireByName 对于我们理解与使用来说复杂程度都很相似,但是其实现功能的复杂度却完全不一样。
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第9张图片
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第10张图片
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第11张图片
虽说对于不同类型处理方式不一致,但是大致的思路还是很相似的,所以函数中只对数据类型进行了详细地注释。

7.3.3 applyPropertyValues

Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第12张图片

7.4 初始化 bean

Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第13张图片
虽说此函数的主要目的是进行客户设定的初始化方法的调用,但是除此之外还有些其他必要的工作。

7.4.1 激活 Aware 方法

Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第14张图片

7.4.2 处理器的应用

BeanPostProcessor 相信大家都不陌生,这是Spring中开放式架构中一个必不可少的亮点,给用户充足的权限去更改或者扩展 Spring,而除了 BeanPostProcessor 外还有很多其他的 PostProcessor,当然大部分都是以此为基础,继承自 BeanPostProcessor。BeanPostProcessor 的使用位置就是这里,在调用客户自定义初始化方法前以及调用自定义初始化方法后分别会调用 BeanPostProcessor 的 postProcessBeforeInitialization 和 postProcessAfterInitialization 方法,使用户可以根据自己的业务需求进行相应的处理。
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第15张图片

7.4.3 激活自定义的 init 方法

Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第16张图片

7.5 注册 DisposableBean

Spring 中不但提供了对于初始化方法的扩展入口,同样也提供了销毁方法的扩展入口。
Spring 系列之 Spring 源码笔记:bean 的加载-下【十一】_第17张图片

你可能感兴趣的:(java,java,spring)