导读
承接上文聊聊 SpringBoot 应用生命周期 (一), 本片重点介绍准备工作完成之后, 从容器刷新开始到 SpringApplication.run() 方法结束的流程. run()方法结束后, 整个应用的启动流程就结束了.
启动阶段
启动阶段大面上分为两部分:
容器刷新
Runners 回调
容器刷新部分是本文重点.
一, 容器刷新
这部分对应的就是 spring framework 原有的容器刷新流程.
1. 准备刷新容器
这个阶段做了一些容器刷新前的准备工作, 如初始化环境变量, 校验必要的变量是否提供.
2. 准备 BeanFactory
这个阶段也有一些值得关注的行为. 有一些 BeanPostProcesser 会在这个阶段添加.
ApplicationContextAwareProcessor bean 初始化之前, 如果实现了某个 Aware 接口, 对应的 set 方法会被调用. 观察下面的代码, 这一票 Aware 实际上注入的都是 applicationContext
- private void invokeAwareInterfaces(Object bean) {
- if (bean instanceof Aware) {
- if (bean instanceof EnvironmentAware) {
- ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
- }
- if (bean instanceof EmbeddedValueResolverAware) {
- ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
- }
- if (bean instanceof ResourceLoaderAware) {
- ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
- }
- if (bean instanceof ApplicationEventPublisherAware) {
- ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
- }
- if (bean instanceof MessageSourceAware) {
- ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
- }
- if (bean instanceof ApplicationContextAware) {
- ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
- }
- }
- }
ApplicationListenerDetector bean 初始化完成后, 如果实现了 ApplicationListener, 会被添加到 ApplicationContext 的监听器中
3. postProcessBeanFactory()
引用官方文档的说明
- Modify the application context's internal bean factory after its standard
- initialization. All bean definitions will have been loaded, but no beans
- will have been instantiated yet. This allows for registering special
- BeanPostProcessors etc in certain ApplicationContext implementations.
这个阶段允许再对容器内部的 beanFactory 进行一些修改. 本阶段完成后, 所有的 bean definitions 都被加载完毕, 但都没有实例化. 这里不免让人疑惑, 这个方法的描述和签名都来自于 BeanFactoryPostProcessor, 为什么要在容器中单独出现? 按照注释的描述:
- // Allows post-processing of the bean factory in context subclasses.
- postProcessBeanFactory(beanFactory);
似乎是为了方便子类容器直接实现此方法从而避免使用 BeanFactoryPostProcessor. 从结果来着, 这个设计并没有达到预期效果, 反而带来了额外的复杂度. 本例中添加了 webApplicationContextServletContextAwareProcessor, 用于 bean 初始化前设置 ServletContextAware,ServletConfigAware 实例 bean 的属性.
4. 回调所有 BeanFactoryPostProcessor
对于注解驱动的 springboot 应用, 在容器创建时就添加了 ConfigurationClassPostProcessor
这个 processor 有多优秀呢, 这里细数一下它主要做了下面几件事:
处理 @ComponentScan 注解. 调用 ComponentScanAnnotationParser, 该 parser 又委托 ClassPathBeanDefinitionScanner 完成组件扫描的工作
递归处理 @Import 注解, 无论是 Import Configuration 还是 ImportSelector 或 ImportBeanDefinitionRegistrar
处理 @ImportResource 注解
这部分完成后, 才符合官方文档的描述: 所有的 bean definitions 都被加载, 但没有实例化.
5. 注册 BeanPostProcessor
注册 BeanPostProcessor, 需要注意的是对于注解驱动的 springboot 应用, 在容器创建时就添加了一票 BeanPostProcessor, 这里列举开发者比较关心的:
AutowiredAnnotationBeanPostProcessor
处理 @Autowired 注解
CommonAnnotationBeanPostProcessor
处理 @Resource 注解
6. initApplicationEventMulticaster()
这部分注册了 Spring 事件发布器 SimpleApplicationEventMulticaster 到容器中, spring framework 时代和 springboot 时代均只有这一个实现.
7. registerListeners()
引用官方文档说明
Add beans that implement ApplicationListener as listeners.
值得注意的是,@EventListener 注解此时还未被处理, 此注解标注的方法此时还不是监听器. 也就是说此时仅有 Springboot 风格的监听器和 spring framework 风格实现了 ApplicationListener 的 Bean 作为监听器.
8. finishBeanFactoryInitialization()
冻结 bean definition metadata, 并实例化所有非延迟初始化的 bean. 这部分收尾阶段会调用 SmartInitializingSingleton 接口的 afterSingletonsInstantiated()方法. EventListenerMethodProcessor(容器创建时就被添加)会处理 @EventListener 注解, 生成对应的监听器并添加到容器中.
9. finishRefresh()
由 DefaultLifecycleProcessor 处理实现了 Lifecycle 接口相关的 bean. 这里通常是调用其 start()方法. 这一点在 spring 內建实现很少, 但是对开发者比较有用. 比如内嵌 Netty 服务时, 可以考虑使用此接口, 让 spring 管理生命周期. 最后发布 ContextRefreshedEvent. 至此 spring 容器启动完成.
10. 注册 ShutdownHook()
这个方法会在虚拟机 shutdown 时被回调, 用于关闭容器.
二, Runners 回调
1. 发布 ApplicationStartedEvent
接上文, 容器已经启动完毕, 发布响应的事件.
2. runners 回调
回调所有 ApplicationRunner,CommandLineRunner.
3. 发布 ApplicationReadyEvent
该事件发布完成后, 表明 SpringApplication 已经可以服务请求.
至此, SpringApplication 启动阶段分析完毕. 下一篇分析结束阶段.
来源: http://www.jianshu.com/p/d4d7f6f0cb59