述
前面介绍了一些Spring容器在初始化时的系统初始化器以及监听器的加载等,Spring容器创建之后,会调用它的refresh方法,refresh的时候会做很多事情:比如完成配置类的解析.各种 BeanFactoryPostProcessor
和 BeanPostProcessor
的注册、国际化配置的初始化、web内置容器的构造等等.
本文来看一下refresh方法的具体源码,看下他具体做了哪些事情
源码跟踪
首先,run方法点进去:
然后找到 refreshContext()
方法,继续往下
这里就是 refresh
方法做的所有的事情,这里面一共调用了 12 个方法,而且是一个同步的代码块,也就是只能有一个线程调用,下面一个一个的看一下他们的具体作用
prepareRefresh()
代码如下:
这个方法做的事情主要就是:
- 配置启动开始时间
- 设置容器状态是active
- 初始化属性源信息(Property)
- 校验环境变量中的必填字段
obtainFreshBeanFactory()
源码如下:
这个方法比较简单,先看一下 refreshBeanFactory()
方法,如下:
然后是 getBeanFactory()
这里默认返回的BeanFactory就是 DefaultListableBeanFactory
prepareBeanFactory()
这里主要是对上面获取到的 BeanFactory 做一些设置,主要如下:
- 设置classloader(用于加载bean),设置表达式解析器(解析bean定义中的一些表达式),添加属性编辑注册器(注册属性编辑器)
- 添加
ApplicationContextAwareProcessor
这个后置处理器 - 取消
EnvironmentAware
,EmbeddedValueResolverAware
,ResourceLoaderAware
,ApplicationEventPublisherAware
,MessageSourceAware
,ApplicationContextAware
这几个接口的自动注入, 这几个接口会交给ApplicationContextAwareProcessor
去处理 - 设置特殊类型对应的bean,
BeanFactory
对应上一步获取到的 beanFactory, 然后ResourceLoader
,ApplicationEventPublisher
,ApplicationContext
这三个接口对应的bean都设置为当前的Spirng容器 - 最后会注入一些其他信息的bean,比如
environment
,systemProperties
等
postProcessBeanFactory()
这个方法的作用主要是 BeanFactory
设置之后再进行后续的一些 BeanFactory
操作, 这个方法在通常情况下是一个空的实现,会交给子类来实现,比如我们项目中添加了web环境的依赖,那就会交给 web 环境的实现类去实现,如下:
再来看一下父类的 postProcessBeanFactory
方法
这里就是对web环境的一些设置,注册一些web环境特有的作用域等
所以这个方法的主要作用就是:
- 交给子类重写,以在
BeanFactory
完成创建后做进一步的设置
invokeBeanFactoryPostProcessors()
这里获取所有的 BeanFactoryPostProcessors
的实现,然后交给 PostProcessorRegistrationDelegate
执行他的 invokeBeanFactoryPostProcessors()
方法
这里需要知道以下两个接口:
BeanFactoryPostProcessor
: 这个接口的作用是对Spring容器中已经存在的Bean做修改, 使用上面获取的BeanFactory
也就是DefaultListableBeanFactory
对 Bean 进行处理BeanDefinitionRegistryPostProcessor
: 这个接口继承自BeanFactoryPostProcessor
,作用跟BeanFactoryPostProcessor
是一样的,他是使用的BeanDefinitionRegistry
对 Bean 进行处理
然后进入 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
方法看一下,这个方法比较长, 分开每个部分看:
第一部分
第二部分
第三部分
这里这个循环,主要是防止 BeanDefinitionRegistryPostProcessor
的实现类中,又注入了一个 BeanDefinitionRegistryPostProcessor
的实现,所以就一直循环,然后直到所有的 BeanDefinitionRegistryPostProcessor
都处理完成
流程图
前面这几部分的流程图如下:
第一部分:
第二部分:
第三部分:
继续往下看,这个方法的源码
第四部分
这里和上面的逻辑基本是一样的,最后会清空一个这个方法产生的缓存,然后这个方法就结束了
总结
总结一下这个方法的作用:
- 调用
BeanDefinitionRegistryPostProcessor
的实现,向容器内添加 Bean 的定义 - 调用
BeanFactoryPostProcessor
的实现,向容器内 Bean 的定义添加属性
registerBeanPostProcessors()
代码如下:
这里调用的是 PostProcessorRegistrationDelegate
的 registerBeanPostProcessors()
方法, 然后看一下具体的实现:
大致流程和上个方法是一样的
- 先找出实现了
PriorityOrdered
接口的BeanPostProcessor
并排序后加到BeanFactory
的BeanPostProcessor
集合中 - 找出实现了
Ordered
接口的BeanPostProcessor
并排序后加到BeanFactory
的BeanPostProcessor
集合中 - 没有实现
PriorityOrdered
和Ordered
接口的BeanPostProcessor
加到BeanFactory
的BeanPostProcessor
集合中
这个方法主要作用就是:
- 找到所有的
BeanPostProcessor
的实现 - 排序后注册到容器中
initMessageSource()
代码如下:
这个方法的作用就是:
- 在Spring容器中初始化一些国际化相关的属性
initApplicationEventMulticaster()
代码如下:
这方法的作用是:
- 初始化事件广播器,注册到容器中
onRefresh()
代码如下:
这里是一个空的模板方法,具体的会交给子类去实现,比如我们的web环境中,就会交给子类 ServletWebServerApplicationContext
去实现,如下:
web环境中的 onRefresh()
方法会创建一个 web 容器,比如tomcat
registerListeners()
代码如下:
这里的 earlyApplicationEvents
这个集合,就是在我们容器的事件派发机制还没有完善的时候发出去的事件,都会存放在这个集合里面,然后在这一步都推送出去
所以这个类的作用就是:
- 把Spring容器内的事件监听器和
BeanFactory
中的事件监听器都添加到事件广播器中 - 派发早期事件
finishBeanFactoryInitialization()
这个方法的作用是:
- 实例化
BeanFactory
中已经被注册但是未实例化的所有实例(懒加载的不需要实例化),比如invokeBeanFactoryPostProcessors
方法中根据各种注解解析出来的类,在这个时候都会被初始化. - 实例化的过程各种BeanPostProcessor开始起作用
这个方法的源码放在下一章详细说明
finishRefresh()
代码如下:
这个方法的主要作用如下:
- 初始化生命周期处理器
- 调用生命周期处理器的
onRefresh()
方法 - 发布
ContextRefreshedEvent
事件 - JMX相关处理
总结
Spring 容器的 refresh 过程就是上述11个方法,内容比较多,每个方法都是大致写了一下流程,可以建个项目debug跟着走一下,会更清晰