Spring依赖注入源码阅读笔记

Posted haoyoung

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring依赖注入源码阅读笔记相关的知识,希望对你有一定的参考价值。

一、调用栈

一次典型的Spring依赖注入的调用栈:

  1. DefaultListableBeanFactory:getBean()
  2. AbstractBeanFactory:doGetBean()
  3. AbstractAutowireCapableBeanFactory:createBean()
  4. AbstractAutowireCapableBeanFactory:createBeanInstance()
  5. SimpleInstantiationStategy:instantiate()
  6. AbstractAutowireCapableBeanFactory:populateBean()
  7. AbstractAutowireCapableBeanFactory:applyPropertyValues()
  8. BeanDefinitionValueResolver:resolveValueIfNecessary()
  9. BeanDefinitionValueResolver:resolveReference()

二、依赖注入过程

  1. getBean:依赖注入的入口,处理参数调用doGetBean()
  2. doGetBean:检查是否需要创建bean,并取得beanDefinition;
    • 单例Bean的处理,从Singleton的缓存中能取到,那就不需要创建。查找缓存的过程:先从singletonObjects中查找;如果没有查找到,又是正在创建的bean,则从earlySingletonObjects中查找;仍未查找到,则通过singletonFactories取得。
    • 原型模式Bean的循环依赖检测,如果检测到正在创建(在prototypesCurrentlyInCreation[threadLocal]中存在),则抛出异常,因为此时,很有可能已经发生了循环依赖。
    • 向上递归查找beanDefinition,当前BeanFactory中不存在该bean的定义,则向父beanFactory递归调用getBean,直到找到为止。
    • 合并父BeanDefinition以取得RootBeanDefinition,如果获取到的bean definition是一个子bean definition,则getMergedLocalBeanDefinition将它与父bean definition合并成一个root bean definition
    • RootBeanDefinition的合法性检测:是否abstract
    • bean定义中显式声明的dependsOn,先进行初始化(递归的):并注册依赖关系,如果检测到循环依赖,则抛出异常。
    • 创建Bean的辅助处理
      • 单例bean:
        1. singletonObjects上锁
        2. 把beanName加入到singletonsCurrentlyInCreation
        3. 创建Bean
        4. singletonsCurrentlyInCreation中移除beanName
        5. 解除singletonObjects锁定
        6. 如果过程中创建了一个实例,将它放入singletonObjectsregisteredSingletons,并从singletonFactoriesearlySingletonObjects中移除
        7. 如果过程中发生了异常,将它从singletonObjectsregisteredSingletonssingletonFactoriesearlySingletonObjects中移除
        8. 处理FactoryBean
      • 原型模式bean:
        1. prototypesCurrentlyInCreation中加入beanName
        2. 创建Bean
        3. prototypesCurrentlyInCreation中移除beanName
        4. 处理FactoryBean
      • 其余scope的bean处理:
        1. 检测scope是否存在
        2. 调用scope.get()方法,并传入getObject()回调。回调中的处理,与prototype下基本一致。
        3. 处理FactoryBean
    • 处理返回数据类型,检测是否可转为requiredType
  3. createBean:创建出一个bean实例,初始化该实例,调用postprocessors等
    • 解析出Class类型,即解析出一个Class<?>,赋到rootBeanDefinition中。但不能直接复制,需要拷贝出一个新的rootBeanDefinition,因为mergedBeanDefinition是共享的,可能有动态解析的class类型,直接赋值可能会有问题。
    • 预处理重写方法,检测重写的方法是否存在,并判断是否是overload。
    • 调用一遍postprocessors调用InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation,这里有可能会返回一个bean的代理。如果返回了bean的代理,那么它将直接执行beanProcessor的postProcessAfterInitialization方法,并返回。
    • 调用钩子方法doCreateBean
  4. doCreateBean
    • 从缓存中移除同名beanfactoryBeanInstanceCache中移除同名bean
    • 创建Bean实例 createBeanInstance
    • 调用一遍postprocessors调用MergedBeanDefinitionPostProcessorpostProcessMergedBeanDefinition
    • Singleton循环依赖的处理:提前将刚创建的实例(未初始化的),放入缓存 如果是Singleton Bean并允许循环依赖,则将刚创建好的实例,放入singletonFactoriesregisteredSingletons中,并从earlySingletonObjects中将同名bean移除
    • Bean初始化 populateBean,用bean definition中的property values初始化得到的bean实例
    • 执行Spring扩展的初始化 initializeBean
      • invokeAwareMethods 如果bean实现了Aware的一些子接口,如BeanNameAware,则将相应的属性set到bean中
      • 调用一遍postprocessors 调用BeanPostProcessor的postProcessBeforeInitialization方法
      • invokeInitMethods
        • 如果bean实现了InitializingBean接口,执行afterPropertiesSet()回调
        • 如果在bean definition中显式自定义了init-method,则会执行一次initMethod回调(通过反射调用)
      • 调用一遍postprocessors 调用BeanPostProcessor的postProcessAfterInitialization方法
    • 注册bean销毁方法回调
  5. createBeanInstance:使用不同的策略,创建bean实例
    • 工厂方法 : 如果在bean definition中显式声明了factory-mothod,则调用工厂方法创建实例。
    • 构造函数 : 选择合适的构造函数实例化
    • CGLIB : 利用CGLIB实例化
  6. populateBean
    • 取得bean definition的property values
    • 调用一遍postprocessors调用InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation方法
    • 处理autowire的注入 autowireByNameautowireByType
    • 调用一遍postprocessors调用InstantiationAwareBeanPostProcessorpostProcessPropertyValues方法
    • 对属性进行注入 applyPropertyValues,属性值注入,解析出运行时该bean factory中其他bean的引用。
      • 获取BeanDefinitionValueResolver。
      • 创建一个新的PropertyValue的list,作为存放解析后的PropertyValue的容器。必须是深拷贝的,否则会修改到原bean definition中的property values。
      • 解析property value:resolveValueIfNecessary()
        针对不同类型的value对象,有不同的convert方式,如value是RuntimeBeanReference类型的,递归调用getBean方法,获取bean。
      • 用BeanWrapper的setPropertyValues方法,批量为bean的属性赋值。最终是调用bean的setXXX()方法赋值。

三、postprocessors及关键方法执行顺序

  1. InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation()
  2. createBeanInstance
  3. MergedBeanDefinitionPostProcessorpostProcessMergedBeanDefinition()
  4. InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation()
  5. autowireByName;autowireByType
  6. InstantiationAwareBeanPostProcessorpostProcessPropertyValues()
  7. applyPropertyValues
  8. BeanPostProcessorpostProcessPropertyValues()
  9. InstantiationAwareBeanPostProcessorpostProcessBeforeInitialization()
  10. invokeInitMethods
  11. InstantiationAwareBeanPostProcessorpostProcessAfterInitialization()

以上是关于Spring依赖注入源码阅读笔记的主要内容,如果未能解决你的问题,请参考以下文章

Spring源码剖析依赖注入实现

Yii源码阅读笔记(三十五)

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段

Spring源码阅读Spring容器启动原理(上)-配置资源加载和注册