【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
- 执行实现了BeanFactoryProcessor的子类BeanDefinitionRegistryPostProcessor的postProcessBeanFactory
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也就被填充完整,这样,一个完整是循环依赖流程走完