SpringBoot 启动分析-refresh()
refresh()
上一篇分析 SpringBoot
启动过程中的 构造过程及 run()
,在构造的过程中,主要是根据应用程序的类型设置 WebApplicationType
,同时根据 spring.factories
的配置读取初始化容器的一些监听器 listeners
和初始化器 initializers
。
而在 run()
中,主要是对应用上下文 ApplicationContext
创建并进行初始化,设置 WebApplicationType
对应的 environment
,然后 refreshContext(context)
,最后加载 listeners start(),running
并加入 SpringRunners
.
在 refreshContext(context)
主要有下面几个工作:
- prepareRefresh()
- prepareBeanFactory()
- postProcessBeanFactory()
- invokeBeanFactoryPostProcessors()
- registerBeanPostProcessors()
- initMessageSource()
- initApplicationEventMulticaster()
- onRefresh()
- registerListeners()
- finishBeanFactoryInitialization()
- finishRefresh()
1 | public void refresh() throws BeansException, IllegalStateException { |
prepareRefresh()
prepareRefresh() 是为 refresh() 进行了准备工作,主要准备工作有:
记录 Spring 容器的启动时间,同时设置 active , closed 的状态
初始化属性源信息 (propertySources),及验证当前环境中的必要的属性是否存在
设置 earlyApplicationListeners & earlyApplicationEvents 属性列表
1 | protected void prepareRefresh() { |
prepareBeanFactory()
prepareBeanFactory() 获取了容器中的 beanFactory 并进行以下操作:
- 设置 bean 加载器 BeanClassLoader(用于 Bean 的加载),bean 表达式解析器 BeanExpressionResolver
- 添加注册属性编辑器 propertyEditorRegistrar,添加 BeanPostProcessor (ApplicationContextAwareProcessor)
- 将几个重要的 bean ( BeanFactory, ResourceLoader, ApplicationEventPublisher, ApplicationContext ) 加载到容器中,后续使用
- 添加 ApplicationListenerDetector 到 beanFactory 中的 beanPostProcessor 列表中
- 检查并注入其他的属性信息,如 loadTimeWeaver, environment 等
1 | protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { |
postProcessBeanFactory()
postProcessBeanFactory() 主要是对设置属性后的 beanFactory 进行了后续的操作, 不同的应用程序类型会由不同的类进行操作,例如在 Servlet 类型中,对应的操作类为 AnnotationConfigServletWebServerApplicationContext, 而在 Reactive 中对应的则是 AnnotationConfigReactiveWebServerApplicationContext,区别在于调用的父类方法 postProcessBeanFactory()上,而读取注册 basePackages、annotatedClass 属性上的 bean 组件都是相同的。
1 | // AnnotationConfigReactiveWebServerApplicationContext.class |
invokeBeanFactoryPostProcessors()
- BeanFactoryPostProcessors 可以对容器中加载 bean,进行属性修改,这里得bean 还未实例化,更没有初始,允许修改 bean 定义
- BeanDefinitionRegistryPostProcessor 是对于 BeanFactoryPostProcessor 的扩展,允许修改 bean 注册器,也就是说可以在 BeanFactoryPostProcessor 之前对 bean 进行定义的修改
1 | @FunctionalInterface |
invokeBeanFactoryPostProcessors() 主要是调用获取当前容器中得 beanPostProessor ( BeanFactoryPostProcessor & BeanDefinitionRegistryPostProcessor ) ,根据 postProcessor 的接口实现 PriorityOrdered & Ordered 进行排序并调用,实现逻辑中 beanDefinitionRegistryPostProcessor 会在 beanFactoryPostProcessor 之前进行调用,保证了两种接口之间的调用顺序.
1 | // 具体的调用过程被委托到 PostProcessorRegistrationDelegate.class 下 |
registerBeanPostProcessors()
registerBeanPostProcessors() 主要是找到容器中的 BeanPostProcessor 类型的 bean,根据具体的实现 PriorityOrdered,Ordered, 进行分类并排序,然后注册到 beanFactory 中的属性列表中,具体的实现被 AbstractApplicationContext 交由 PostProcessorRegistrationDelegate.registerBeanPostProcessors 实现。
1 | // PostProcessorRegistrationDelegate.class |
initMessageSource()
MessageSource 是 Spring 支持国际化的一种方式,通过 MessageSource,可以读取根据 Locale 的具体位置设置,自动选择对应的 messages.properties (messages_en.properties, messages_ch_properties) 配置文件。然后根据业务需求 getMessage() 的到我们要的配置信息。
而 initMessageSource() 的作用就在于读取 messageSource bean,并进行初始化
1 | protected void initMessageSource() { |
initApplicationEventMulticaster()
通常,我们在 Spring 中 发送一个事件 event 是采用 applicationContext.pushEvent() ,实际上,具体的事件发送广播是被交由 applicationEventMulticaster 发送,具体的过程将后续将会出一篇 Spring Event 事件机制进行介绍。而 initApplicationEventMulticaster() 就是将 applicationEventMulticater 注册到 beanFactory 容器中。
1 | // AbstractApplicationContext.class |
onRefresh()
onRefresh() 和上面的 postProcessBeanFactory() 一样,都是一个模板方法,具体的实现会根据 webApplicationType 的具体类型找到对应的 GenericWebApplicationContext || ReactiveWebServerApplicationContext 等,具体实现都有所不同。
1 | // AbstractApplicationContext.class |
registerListeners()
在上面的步骤中,我们已经将事件广播器 applicationEventMulticaster 注册到了容器中,有了广播器,那么接下来就是收集容器中的所有 listener bean 组件,将他们保存在集合中,以便事件发布时能够遍历监听器列表,通过适配 eventType,找到对应的 listener 并进行处理。
1 | // AbstractApplicationContext.class |
finishBeanFactoryInitialization()
finishBeanFactoryInitialization(beanFactory) 的主要作用是实例化所有的单例 bean ( 非 Lazy ),这个时候,容器中的 beanPostProcessor 将会开始起作用。
1 | protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { |
finishRefresh()
finishRefresh() 的作用是做 refesh() 后的额外操作,例如清除上下文缓存 ( ASM 数据 ),初始化 生命周期处理器 LifeCycleProcessor,发布 上下文已经刷新事件 ContextRefreshedEvent.
1 | AbstractApplicationContext.class |
总结
可以看出,refresh() 在 SpringBoot 的启动过程中,扮演着非常重要的角色,包括了注册重要的 bean 组件,实例化容器中的 bean,processors 之间的调用等,通过分析后,我们可以了解到了我们日常工作中使用到的各种实现例如 InstantiationAwareBeanPostProcessor ,Listener, LifeCycleProcessor 等组件的调用顺序及功能。
同时,refresh() 过程也很好的展示了 bean 的生命周期中各个组件的位置及作用,也对于我们理解 Spring 容器有了更好的理解。