美文网首页
Spring配置文件装配bean大体流程

Spring配置文件装配bean大体流程

作者: SimbaF | 来源:发表于2018-12-06 18:02 被阅读0次
    容器启动的模板方法

    1. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

    此方法主要完成对配置文件中bean定义解析为BeanDefinition的工作,并将BeanDefinition注册到registry中.

    1.1 刷新BeanFactory

    1.1.1 若当前已存在BeanFactory,对其进行销毁和关闭

    1.1.2 创建DefaultListableBeanFactory作为默认容器,设置容器的序列化id并定制一些属性(allowBeanDefinitionOverriding和allowCircularReferences)

    1.1.3 装载BeanDefinition

    1.1.3.1 构造一个XmlBeanDefinitionReader,并对其进行一些设置
    1.1.3.2 BeanDefinition装载工作委托给XmlBeanDefinitionReader来处理
    1. 获取配置文件地址
    2. 循环处理每个配置文件地址来处理BeanDefinition的装载
       2.1 通过ResourceLoader将配置文件地址解析为Resource
       2.2 通过Resource来装载BeanDefinition
        2.2.1 将配置文件资源解析为Document
        2.2.2 构造一个BeanDefinitionDocumentReader(实现类为DefaultBeanDefinitionDocumentReader),将Document解析解析为BeanDefinition并注册的工作委托给这个DefaultBeanDefinitionDocumentReader处理.
        2.2.2.1 构造一个BeanDefinitionParserDelegate,将Document中各个节点元素的解析处理工作委托给这个BeanDefinitionParserDelegate来完成.包括默认命名空间节点元素的解析和自定义命名空间节点元素的解析(这部分为重点,具体放到1.3深入总结).

    1.2 获取刷新后新的BeanFactory,并将其返回

    1.3 默认命名空间节点元素和自定义命名空间节点元素的解析

    以默认命名空间的<bean>标签解析为例

    1.3.1 BeanDefinitionParserDelegate将Element解析为BeanDefinitionHolder

    • 处理beanName和alias
    • Element解析为AbstractBeanDefinition
      1. 生成一个GenericBeanDefinition(AbstractBeanDefinition的子类),记为bd
      2. 为bd设置一些属性.如scope,lazy-init,depends-on,init-method等等等等.
      3. 解析该bean元素下的一些子元素属性设置
      4. 构造参数子元素解析(对应以后的构造注入,如<constructor-arg index="0" ref="t"/>)
      5. 属性子元素解析(对应以后的设值注入,如<property name="start" value="a"/>),重点分析一下这里属性注入方式
        5.1 处理属性或子元素(源码注解:Should only have one child element: ref, value, list, etc.),生成相应的对象并将其返回
        5.2 以上述返回的对象和属性名构造PropertyValue.(这个类很关键,xml配置bean的方式下,设值注入的每个属性依赖就是通过每个PropertyValue来实现的)
        5.3 向MutablePropertyValues添加上述PropertyValue.(这是依赖注入另一个关键类,AbstractBeanDefinition内部持有一个MutablePropertyValues属性propertyValues,通过这个属性保存所有的依赖,MutablePropertyValues内部持有一个List<PropertyValue> propertyValueList,实际上就是将前面生成的每一个PropertyValue添加到这个list中)
    • 返回AbstractBeanDefinition

    1.3.2 注册BeanDefinition以及注册别名alias

    到这里只是完成了将配置文件中定义的bean解析为Spring为Bean专门定义的数据结构BeanDefinition,还未完成实例化和依赖的注入,只是将数据解析和准备完成.



    2. invokeBeanFactoryPostProcessors(beanFactory);

    实现BeanFactoryPostProcessor接口的后置处理器的处理逻辑调用,BeanFactoryPostProcessor是对BeanDefinition的后置处理(此时bean还未进行实例化和依赖注入,只是以解析后的BeanDefinition形式存在)


    3. registerBeanPostProcessors(beanFactory);

    注册BeanPostProcessor,这里只是注册,还未实际调用


    4. finishBeanFactoryInitialization(beanFactory);

    这里完成bean的实例化,依赖注入,后置处理等等一些列操作.关键方法beanFactory.preInstantiateSingletons();

    4.1 获取所有的注册的beanName,循环遍历处理以完成实例化和依赖注入

    4.1.1 获取BeanDefinition

    4.1.2 对于满足条件:非抽象&&单例&&非延迟初始化的BeanDefinition,通过getBean方法完成实例化并获取Bean

    4.1.2.1 从单例缓存中获取实例
    4.1.2.2 如果取得实例不为空,若该实例为普通Bean,直接返回;若为FactoryBean,尝试从FactoryBean缓存中获取,存在则返回,否则的话最终通过FactoryBean的getObject方法获取对象,并存缓存.(getObjectForBeanInstance方法源码注解:Get the object for the given bean instance, either the bean instance itself or its created object in case of a FactoryBean.)
    4.1.2.3 如果取得实例为空(重点分支流程)
    • 获取父容器,若满足条件父容器不为空&&当前容器不包含该beanName的BeanDefinition,返回调用父容器的getBean方法的结果,否则不执行这一步,继续向下执行
    • 获取BeanDefinition
    • 获取解析后存于BeanDefinition中的依赖(String[]),循环处理每个依赖
      1. 判断是否循环depends-on关系,是则抛出异常
      2. 注册依赖
      3. 递归调用getBean方法,先处理依赖的Bean(也就是先递归到最底层处理没有任何依赖的Bean,在一层一层返回上层处理,这样保证了依赖的底层Bean会先被实例化)
    • 如果BeanDefinition中的数据记录的该bean是单例的,那么最终通过createBean方法(该方法由AbstractAutowireCapableBeanFactory实现)来完成Bean的初始化,依赖注入,各种后置处理等等工作(这里只分析单例情况,prototype情况不分析了)
      1. 为BeanPostProcessors提供返回代理而不是目标bean实例的机会.(源码注释:Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.)
        1.1 对InstantiationAwareBeanPostProcessor接口的实现类调用其前置方法postProcessBeforeInstantiation,只要有一个接口实现类的postProcessBeforeInstantiation方法调用成功(即返回的结果不为null),后面其他接口实现类就不再执行
        1.2 在上面1.1执行成功的前提下,执行所有的BeanPostProcessor的后置处理方法postProcessAfterInitialization
      2. doCreateBean方法(重要方法)
        2.1 createBeanInstance方法,使用适当的实例化策略为指定的bean创建新实例:工厂方法,构造函数自动装配或简单实例化(源码注释:Create a new instance for the specified bean, using an appropriate instantiation strategy:factory method, constructor autowiring, or simple instantiation.).该方法返回一个BeanWrapper,BeanWrapper中通过一个内部属性object来持有bean,此时的bean只是初步创建,还未进行依赖注入
        2.2 执行MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法
        2.3 populateBean方法用来完成依赖注入
         2.3.1 获取BeanDefinition的PropertyValues
         2.3.2 调用InstantiationAwareBeanPostProcessors的处理方法postProcessAfterInstantiation,为任何InstantiationAwareBeanPostProcessors提供在设置属性之前修改bean状态的机会.例如,这可以用于支持现场注入的样式(源码注释:Give any InstantiationAwareBeanPostProcessors the opportunity to modify the state of the bean before properties are set. This can be used, for example, to support styles of field injection.)
         2.3.3 autowireByName或者autowireByType,这里分析一下autowireByType
          2.3.3.1 找到需要依赖注入的属性,不包括基本类型和String等这种简单的类型
          2.3.3.2 处理依赖,获取被注入bean
          2.3.3.3 将上述bean添加到MutablePropertyValues的propertyValueList中(从原List中遍历去除同名PropertyValue以保证是同一个属性,合并属性并返回;若遍历原List时没有同一名称的属性,则直接添加到List中)
          2.3.3.4 调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法进行一些后置处理(注解注入@autowired的实现就是通过这里AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法来实现的)
          2.3.3.5 applyPropertyValues应用属性,完成注入.
        2.4 initializeBean方法的执行,初始化给定的bean实例,应用工厂回调以及init方法和bean后处理器(源码注释:Initialize the given bean instance, applying factory callbacks as well as init methods and bean post processors.)
         2.4.1 invokeAwareMethod方法调用,完成一些Aware接口方法处理,BeanNameAware,BeanClassLoaderAware,BeanFactoryAware
         2.4.2 BeanPostProcessor的postProcessBeforeInitialization处理方法
         2.4.3 invokeInitMethods方法调用,执行一些init方法
         2.4.4 BeanPostProcessor的postProcessAfterInitialization处理方法



    注:

    Spring Bean的实例化和初始化两个阶段的主要作用:

    1、实例化Instantiation—-实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中,可理解为createBeanInstance方法阶段初步创建的bean.

    2、初始化Initialization—-初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性,可理解为依赖注入阶段

    相关文章

      网友评论

          本文标题:Spring配置文件装配bean大体流程

          本文链接:https://www.haomeiwen.com/subject/ejhocqtx.html