spring学习之源码分析bean的创建

7次阅读

共计 1670 个字符,预计需要花费 5 分钟才能阅读完成。

在 spring 学习之源码分析 –AbstractApplicationContext 之 refresh 中,提及了容器初始化时调用 createBean 创建 bean,但是没有细讲,这边就详细的讲解一下。

createBean

  1. 解析 class 类型
  2. 如果有 lookup-method 和 replaced-method 属性先处理。如果有某个属性,就调用动态代理,进行相应的拦截。另外,有些方法可能存在重载的情况,在这里也会一并处理了,如果只有一个方法名,会标记为没有重载,这样后面调用方法的时候,就可以直接调用了。
  3. resolveBeforeInstantiation,先判断是否解析过了,如果没有,看看 InstantiationAwareBeanPostProcessor 能不能生成 bean–applyBeanPostProcessorsBeforeInitialization,这个 bean 不一定是普通的 bean,也可能是动态代理或者其他方式生成的 bean。如果可以生成 bean,就标志位解析过了,并且调用后置处理器处理 –applyBeanPostProcessorsAfterInitialization。
  4. 如果没有生成,调用 doCreateBean 方法,下面我们看看这部分内容

doCreateBean

doCreateBean 方法

  1. 如果是单例,取出 bean 并清空缓存。
  2. 如果取出的 bean 为空,实例化 bean,具体实例化过程下面讲解。
  3. 创建后,MergedBeanDefinitionPostProcessor 进行后置处理,这个 MergedBeanDefinitionPostProcessor 包括 AutowiredAnnotationBeanPostProcessor 等。
  4. 依赖处理
  5. 实例化后,对 bean 各个属性进行赋值。见 populateBean。
  6. 赋值后,调用 init 方法,InitializingBean 这些。见 initializeBean
  7. 再检查一下依赖,看看是不是初始化方法改变了什么
  8. 根据 scope 注册 DisposableBean,registerDisposableBeanIfNecessary 方法

createBeanInstance

createBeanInstance 方法

  1. 先检查是否有类的访问权限,如果没有权限,只能抛异常了
  2. 看看有没有 Supplier 回调,如果有回调,就让别人回调创建
  3. 看看有没有工厂方法回调,如果有回调,就让工厂方法回调创建
  4. 如果没有其他人插手了,就开始自己创建了。实例化类要么有参构造要么无参构造,由于每次解析很耗性能,所以要把构造结果缓存起来。既然有缓存,当然是先查询是否有缓存,如果有,再根据缓存选择无参构造还是有参构造。
  5. 如果缓存没有,就去解析,解析后缓存结果,以及选择无参构造还是有参构造。

populateBean

populateBean 方法
实例化了 bean,给 bean 的属性赋值。

  1. 先判断是否有属性需要赋值
  2. InstantiationAwareBeanPostProcessor 后置处理,是否继续填充属性。我们可以看到,spring 在很多阶段做了很多这类后置处理。
  3. 根据名称或类型,获取需要注入的 bean。根据 name 比较简单,就是 getBean,根据类型解析就有点复杂了。
  4. 赋值前,InstantiationAwareBeanPostProcessor 后置处理验证属性
  5. 依赖检查
  6. 赋值

initializeBean

initializeBean 方法
bean 构造完了,也给各个属性赋值了,先在就看看有没有初始化方法了。

  1. Aware 处理,也就是说,如果实现了 Aware 接口,会注入一些属性给这些 bean
  2. 后置处理器处理,调用 BeanPostProcessor 的 postProcessBeforeInitialization
  3. invokeInitMethods,如果实现了 InitializingBean 接口,就调用他的 afterPropertiesSet 方法,如果有自定义方法,就继续调用自定义方法。例子请查看 spring 学习之 bean 生命周期的管理
正文完
 0