SpringFramework源码解析——Spring应用上下文是如何刷新的?
- 1. 背景
- 2. Spring应用上下文刷新流程
- 2.1. 准备要刷新的应用上下文(prepareRefresh)
- 2.2. 获取应用上下文使用的Bean工厂(obtainFreshBeanFactory)
- 2.3. 准备应用上下文使用的Bean工厂(prepareBeanFactory)
- 2.4. 应用上下文子类对Bean工厂进行后置处理(postProcessBeanFactory)
- 2.5. Bean工厂后置处理器后置处理(invokeBeanFactoryPostProcessors)
- 2.6. 注册Bean后置处理器(registerBeanPostProcessors)
- 2.7. 初始化消息源(initMessageSource)
- 2.8. 初始化应用事件广播器(initApplicationEventMulticaster)
- 2.9. 应用上下文子类刷新(onRefresh)
- 2.10. 注册事件监听器(registerListeners)
- 2.11. 完成Bean工厂的初始化(finishBeanFactoryInitialization)
- 2.12. 完成刷新(finishRefresh)
1. 背景
1.1. BeanFactory和ApplicationContext有什么区别?
Bean工厂BeanFactory
和应用上下文ApplicationContext
两者都是IoC
容器。
- 从功能上看,
ApplicationContext
是BeanFactory
的超集,提供了环境,事件,资源,国际化,类型转换等一系列的企业级应用特性,这在接口的定义上也有体现。 - 从实现上看,
ApplicationContext
接口继承了BeanFactory
接口以及其它一系列的接口,本质上应用上下文是通过委派给内建的Bean工厂实现IoC
容器相关的功能的。 - 从面向对象上看,
BeanFactory
是面向Spring框架开发者的,而ApplicationContext
是面向Spring框架使用者的。
1.2. 为什么要使用ApplicationContext?
Spring应用在启动时,会根据指定的XML配置文件或配置类进行Bean定义的加载,Bean的创建等,也就是应用上下文的刷新。通常来说,作为框架使用者我们会把IoC
容器的创建交给Spring框架去做,而不需要显式地创建一个Bean工厂完成上面的动作。再者,应用上下文提供了一系列的企业级特性,这些是Bean工厂不具备的。
1.3. ApplicationContext的继承体系
ApplicationContext
接口是一个中心接口,它继承了一系列的接口。
- 继承了
HierarchicalBeanFactory
和ListableBeanFactory
接口表明其拥有IoC
容器相关的功能。 - 继承了
ResourcePatternResolver
接口表明其拥有资源加载的能力。 - 继承了
MessageSource
接口表明其拥有消息解析的能力,如国际化。 - 继承了
ApplicationEventPublisher
接口表明其拥有发布事件的能力。 - 继承了
EnvironmentCapable
接口表明其拥有获取环境的能力。
其继承体系类图如下:
2. Spring应用上下文刷新流程
2.1. 准备要刷新的应用上下文(prepareRefresh)
- 设置应用上下文的启动时间戳为当前时间;
- 设置应用上下文的已关闭标识为
false
; - 设置应用上下文的激活标识为
true
; - 初始化属性源(模板方法模式,默认为空实现,应用上下文子类可重写此方法);
- 验证环境中必须的属性。
对应源码所在位置:
AbstractApplicationContext#prepareRefresh
。
2.2. 获取应用上下文使用的Bean工厂(obtainFreshBeanFactory)
- 刷新Bean工厂;
- 返回Bean工厂。
刷新Bean工厂的具体实现为AbstractRefreshableApplicationContext#refreshBeanFactory
,步骤如下:
- 如果Bean工厂已经存在:
1.1. 销毁Bean;
1.2. 关闭Bean工厂; - 创建Bean工厂;
- 自定义Bean工厂(配置Bean定义是否允许被覆盖和是否允许循环依赖);
- 加载Bean定义(模板方法模式,应用上下文子类可实现此抽象方法)。
对应源码所在位置:
AbstractApplicationContext#obtainFreshBeanFactory
。
2.3. 准备应用上下文使用的Bean工厂(prepareBeanFactory)
- 设置Bean工厂的Bean类加载器;
- 设置Bean工厂的Bean表达式解析器;
- 设置Bean工厂的属性编辑器;
- 注册Bean后置处理器
ApplicationContextAwareProcessor
; - 注册内建的依赖(
BeanFactory
,ResourceLoader
,ApplicationEventPublisher
和ApplicationContext
); - 注册Bean后置处理器
ApplicationListenerDetector
; - 注册内建的单例对象(
environment
,systemProperties
,systemEnvironment
和applicationStartup
)。
对应源码所在位置:
AbstractApplicationContext#prepareBeanFactory
。
Bean后置处理器ApplicationContextAwareProcessor
首先会判断Bean的类型是否是以下几种Aware
子接口;如果是的话,会调用对应接口的setter
方法来设置值。
EnvironmentAware
EmbeddedValueResolverAware
ResourceLoaderAware
ApplicationEventPublisherAware
MessageSourceAware
ApplicationContextAware
ApplicationStartupAware
对应源码所在位置:
ApplicationContextAwareProcessor#postProcessBeforeInitialization
。
Bean后置处理器ApplicationListenerDetector
首先会判断Bean的类型是否是ApplicationListener
;如果是的话,会调用AbstractApplicationContext#addApplicationListener
方法在应用上下文中注册该Bean为事件监听器。
对应源码所在位置:
ApplicationListenerDetector#postProcessAfterInitialization
。
2.4. 应用上下文子类对Bean工厂进行后置处理(postProcessBeanFactory)
允许应用上下文子类对Bean工厂进行后置处理(模板方法模式,默认为空实现,应用上下文子类可重写此方法)。
对应源码所在位置:
AbstractApplicationContext#postProcessBeanFactory
。
2.5. Bean工厂后置处理器后置处理(invokeBeanFactoryPostProcessors)
委派给PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
方法,调用Bean工厂后置处理器的后置处理方法。处理逻辑如下:
- 执行在应用上下文中静态注册的Bean定义注册器后置处理器的注册后置处理方法;
- 排序并执行Bean工厂中实现了
PriorityOrdered
接口的Bean定义注册器后置处理器的注册后置处理方法; - 排序并执行Bean工厂中实现了
Ordered
接口的Bean定义注册器后置处理器的注册后置处理方法; - 执行Bean工厂中剩余的Bean定义注册器后置处理器的注册后置处理方法;
- 执行Bean定义注册器后置处理器的工厂后置处理方法;
- 执行常规Bean工厂后置处理器的后置处理方法;
- 排序并执行Bean工厂中实现了
PriorityOrdered
接口的Bean工厂后置处理器的后置处理方法; - 排序并执行Bean工厂中实现了
Ordered
接口的Bean工厂后置处理器的后置处理方法; - 执行Bean工厂中剩余的常规Bean工厂后置处理器的后置处理方法;
对应源码所在位置:
AbstractApplicationContext#invokeBeanFactoryPostProcessors
。
2.6. 注册Bean后置处理器(registerBeanPostProcessors)
委派给PostProcessorRegistrationDelegate#registerBeanPostProcessors
方法,注册Bean后置处理器。处理逻辑如下:
- 排序并注册Bean工厂中实现了
PriorityOrdered
接口的Bean后置处理器; - 排序并注册Bean工厂中实现了
Ordered
接口的Bean后置处理器; - 注册Bean工厂中剩余的常规Bean后置处理器;
- 重新注册合并Bean定义Bean后置处理器。
对应源码所在位置:
AbstractApplicationContext#registerBeanPostProcessors
。
2.7. 初始化消息源(initMessageSource)
如果Bean工厂中没有Bean名称为messageSource
的消息源,则创建一个消息源并注册到Bean工厂中。
对应源码所在位置:
AbstractApplicationContext#initMessageSource
。
2.8. 初始化应用事件广播器(initApplicationEventMulticaster)
如果Bean工厂中没有Bean名称为applicationEventMulticaster
应用事件广播器,则创建一个应用事件广播器并注册到Bean工厂中。
对应源码所在位置:
AbstractApplicationContext#initApplicationEventMulticaster
。
2.9. 应用上下文子类刷新(onRefresh)
允许应用上下文子类进行自定义刷新(模板方法模式,默认为空实现,应用上下文子类可重写此方法)。
对应源码所在位置:
AbstractApplicationContext#onRefresh
。
2.10. 注册事件监听器(registerListeners)
- 获取所有静态声明的事件监听器并注册
- 从Bean工厂中获取Bean类型为
ApplicationListener
的Bean并注册。
对应源码所在位置:
AbstractApplicationContext#registerListeners
。
2.11. 完成Bean工厂的初始化(finishBeanFactoryInitialization)
- 设置转换服务;
- 注册嵌入值解析器;
- 冻结配置;
- 实例化所有非懒初始化的单例Bean。
对应源码所在位置:
AbstractApplicationContext#finishBeanFactoryInitialization
。
2.12. 完成刷新(finishRefresh)
- 重置缓存;
- 清除资源缓存;
- 初始化生命周期处理器;
- 执行生命周期处理器的刷新方法;
- 发布应用上下文已刷新事件。
对应源码所在位置:
AbstractApplicationContext#finishRefresh
。
目录
- 1. 背景
- 2. Spring应用上下文刷新流程
- 2.1. 准备要刷新的应用上下文(prepareRefresh)
- 2.2. 获取应用上下文使用的Bean工厂(obtainFreshBeanFactory)
- 2.3. 准备应用上下文使用的Bean工厂(prepareBeanFactory)
- 2.4. 应用上下文子类对Bean工厂进行后置处理(postProcessBeanFactory)
- 2.5. Bean工厂后置处理器后置处理(invokeBeanFactoryPostProcessors)
- 2.6. 注册Bean后置处理器(registerBeanPostProcessors)
- 2.7. 初始化消息源(initMessageSource)
- 2.8. 初始化应用事件广播器(initApplicationEventMulticaster)
- 2.9. 应用上下文子类刷新(onRefresh)
- 2.10. 注册事件监听器(registerListeners)
- 2.11. 完成Bean工厂的初始化(finishBeanFactoryInitialization)
- 2.12. 完成刷新(finishRefresh)