【spring源码分析】一、spring Refresh流程

1.初始化AnnotatedBeanDefinitionReader

  • 主要用于把spring内置的6种beanFactoryPostProcess注册到容器中
  • 提供给程序员注册bd,主要是加了@Configuration的类。

2.初始化ClassPathBeanDefinitionScanner

  • 程序员在外部可以调用,用于bd的扫描
  • spring内部不是用它,而是自己重新new scanner来扫描

3.执行register,把我们自己的配置类注册到spring容器

4.执行refresh(),spring生命周期主要的功能都是在这里实现,下述步骤为详解

5.执行invokeBeanFactoryPostProcessors,完成bean的扫描、解析、PostBeanProcessors和BeanFactoryPostProcessors的执行等

  • 先执行beanFactoryPostProcessor的子接口BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法

    • 先执行外部通过context.add进来的BeanDefinitionRegistryPostProcessor
    • 再执行spring内部的BeanDefinitionRegistryPostProcessor,正常情况这里只有ConfigurationClassPostProcessor,为初始化AnnotatedBeanDefinitionReader的时候注册进的spring,扫描、解析、校验,初始化bd等
    • 接着执行程序员通过注解注册的 并且特殊的比如 实现了PriorityOrdered,Order的BeanDefinitionRegistryPostProcessor
    • 最后执行其他普通的BeanDefinitionRegistryPostProcessor
  • 再执行直接实现了beanFactoryPostProcessor类的postProcessBeanFactory方法

    • 执行实现了BeanFactoryProcessor的子类BeanDefinitionRegistryPostProcessor的postProcessBeanFactory
      • 先执行外部通过context.add进来的BeanDefinitionRegistryPostProcessor
      • 再执行接着执行程序员通过注解注册的BeanDefinitionRegistryPostProcessor
    • 再执行外部通过context.add进来的beanFactoryPostProcessor
    • 接着执行程序员通过注解注册的 并且特殊的比如 实现了PriorityOrdered,Order的beanFactoryPostProcessor
    • 最后执行其他普通的beanFactoryPostProcessor

6.上述ConfigurationClassPostProcessor把将类变成bd的详解

  • 从BeanDefinitionRegistry中获取所有的bd,取出bd不是full或者lite,并且是Configuration类的bd(check的时候会给class添加full或者lite,纯configuration为full,Component、ComponentScan、Import、ImportResource为lite)

  • 遍历解析配置类

    • 先处理配置类的内部类

    • 处理@PropertrySource 环境配置

    • 处理@ComponentScan,会调用ClassPathBeanDefinitionScanner,根据包路径,和匹配规则扫描出合格类,放到map中

    • 处理@Import

      a.先处理 ImportSelect,执行selectImports(),

      b.然后处理 ImportBeanDefinitionRegistrar接口,会放到该bd的一个Map中,循环map统一去执行实现方法registerBeanDefinitions

      c.最后处理普通的类,同样会递归去解析该bd。aop

    • 处理@ImportResource

    • 处理@Bean

    • 处理接口bd

  • 将所有的合格的类,转换成bd,注册到beanDefinitionRegistry。

7.注册beanPostProcessor后置处理器,国际化等等

8.finishBeanFactoryInitialization真正实现实例化bean(单例非懒加载),getbd,把bd变成springbean,遍历map,各种验证,都验证通过,这里有两次getSingleton

9.先合并bd,getMergedLocalBeanDefinition,进行一些简单的验证

关于循环依赖的一些重要类

singletonObjects 一级缓存,完整的bean

singletonFactories 二级缓存,存的是代理bean工厂

earlySingletonObjects 三级缓存,一般是是半成品的bean

isSingletonCurrentlyInCreation 就是一个set集合,存放正在执行中的beanName

注:这里的一级缓存和三级缓存没有明确的定义

10.第一次getSingleton,一般单例池中是不存在的,并且不是正在创建bean的set集合中isSingletonCurrentlyInCreation(在多线程、循环依赖的情况下,单例池中不为null)

  • 存在,直接拿出来
  • 不存在,并且不在isSingletonCurrentlyInCreation中,返回null
  • 不存在,在isSingletonCurrentlyInCreation中,从三级缓存中中拿
    • 三级缓存中存在,直接拿
    • 三级缓存中不存在,通过二级工厂拿代理bean工厂,获得该bean,然后将得到bean放到三级缓存中,移除二级缓存(留一个问题,这里的二级工厂是怎么会有该工厂bean的,isSingletonCurrentlyInCreation里又是什么时候会有beanName的)

11.第一次getSingleton如果没取到,又是一系列是否存在正在创建当原型集合当中,是否有父子容器验证等等校验一切校验通过,执行第二次getSingleton,先判断一级缓存是否存在

  • 存在,直接拿出来
  • 不存在
    • 首先将beanName放到正在创建bean的set集合中,表示正在创建该bean,判断是不是在在排除对象中
    • lambda延迟机制,就会调用表达式中,也就是createBean,这时候是正在获取代理bean工厂会走一个完整的bean 的生命周期
    • 根据注入模型推断构造方法创建对象
    • 如果是单例的,正在创建的bean,且此时单例池中没有,把工厂对象存到二级缓存中,删除三级缓存

12.完成属性注入

13.执行生命周期各种回调以及aop等

eg:class A 和ClassB相互引用

1)a先执行第一次getSingleton,一级缓存中无,并且没有在正在创建的bean名单中,一系列校验后

2)执行第二次getSingleton,此时一级缓存中还是无,这个时候把nameA放到正在创建的bean集合中,推断a的构造方法,去创建a对象,把工厂对象a放到二级缓存中,执行a的属性注入,此刻发现a中有注入b,spring容器中还没有b,这个时候去doGetBean b

3)b第一次getSingleton,一级缓存中无,并且b没有在正在创建的bean名单中,一系列校验后

4)执行b的第二次getSingleton,此时一级缓存中还是无,这个时候把nameb放到正在创建的bean集合中,推断b的构造方法,去创建b对象,把工厂对象b放到二级缓存中,执行b的属性注入,此刻发现b中有注入a,spring容器中还没有a,这个时候去doGetBean a

5)a再一次执行第一次getSingleton,一级缓存中无,由2)得知此刻a在正在创建的bean名单中,并且二级缓存中存在a,去看三级缓存中是否存在,显然,现在是不存在的,通过二级工厂拿代理beanA工厂,获得该beanA,然后将得到beanA放到三级缓存中,移除二级缓存A,返回半成品的beanA(生命周期还没有走完 ),继续第4)步b接下来的生命周期过程,注入其他属性,执行b的生命周期各种回调以及aop等,完成b的整个生命周期

6)执行2)a的接下来生命周期,此时a中注入的b已经是一个完整的bean,执行a的生命周期各种回调以及aop等,完成a的整个生命周期,因为b中注入的是a的引用,此时,b中的a也就被填充完整,这样,一个完整是循环依赖流程走完

原文地址:https://www.cnblogs.com/faramita/p/14603021.html