透彻理解SpringBoot启动原理(二)
- 照旧一张Spring启动顺序图
- 我们对Spring启动原理有多少理解呢(问题回顾)
- 关于Spring启动原理的若干问题
- 1.init-method、PostConstruct、afterPropertiesSet 三个方法的执行顺序。
- 2.Spring 何时装配Autowire属性,PostConstruct方法中引用 Autowired 字段是否会空指针?
- 3.PostConstruct 中方法依赖ApplicationContextAware拿到 ApplicationContext,两者的顺序谁先谁后?是否会出现空指针!
- 4.项目应该如何监听 Spring 的启动就绪事件。
- 5.项目如何监听Spring 刷新事件。
- 6.Spring就绪事件和刷新事件的执行顺序和区别。
- 7.Http 流量入口何时启动完成。
- 8.项目中在 init-method 方法中注册 Rpc是否合理?什么是时候注册最合理?
- 9.项目中在 init-method 方法中注册 MQ消费组是否合理?什么是合理的时机?
- 1.Spring还未完全启动,在 PostConstruct 中调用 getBeanByAnnotation能否获得准确的结果?
- 深入源码
照旧一张Spring启动顺序图
Hellow! 这次再看这张图,请认真回顾下第一篇所讲解的启动顺序,打破遗忘曲线,我们再一次一起看一下这张 Spring启动顺序图
我们对Spring启动原理有多少理解呢(问题回顾)
我在这里为大家准备了一些很细节但贯穿整个spring启动流程的常见问题:
- Spring常见的流量入口有哪些?
- SpringBoot集成Tomcat,如果Http流量先进入了,此时Spring还未启动完成,怎么办?那Tomcat是何时开启端口对外服务的呢?
- Spring集成RPC框架,RPC框架何时注册暴露服务,在Spring那个扩展点注册呢?
- Spring集成MQ消费组,MQ消费者何时开始消费,在Spring那个扩展点“注册消费者”?
- Spring还未完全启动,在 PostConstruct 中调用 getBeanByAnnotation 能否获得准确的结果?;
- 项目应该如何监听 Spring 的启动就绪事件?项目如何监听Spring 刷新事件?
- Spring就绪事件和刷新事件的执行顺序和区别?
- Http 流量入口何时启动完成?
- PostConstruct 中方法依赖ApplicationContextAware拿到 ApplicationContext,两者的顺序谁先谁后?是否会出现空指针!
- init-method、PostConstruct、afterPropertiesSet 三个方法的执行顺序?
如上10个问题,作为在Spring框架中苦苦挣扎的你,能理解并解答出几个呢?
关于Spring启动原理的若干问题
----------------------还记得(一)中打印顺序的图吗,请记好!!
1.init-method、PostConstruct、afterPropertiesSet 三个方法的执行顺序。
PostConstruct,afterPropertiesSet,init-method
2.Spring 何时装配Autowire属性,PostConstruct方法中引用 Autowired 字段是否会空指针?
Autowired装配依赖发生在 PostConstruct之前,不会出现空指针!
3.PostConstruct 中方法依赖ApplicationContextAware拿到 ApplicationContext,两者的顺序谁先谁后?是否会出现空指针!
ApplicationContextAware 会先执行,不会出现空指针!但是当Autowired没有找到对应的依赖,并且声明了非强制依赖时,该字段会为空,有潜在 空指针风险。
4.项目应该如何监听 Spring 的启动就绪事件。
通过SmartLifecyle start方法,监听Spring就绪 。适合在此开启入口流量!
5.项目如何监听Spring 刷新事件。
监听 Spring Event ContextRefreshedEvent
6.Spring就绪事件和刷新事件的执行顺序和区别。
Spring就绪事件会先于 刷新事件。两者都可能多次执行,要确保方法的幂等处理,避免重复注册问题
7.Http 流量入口何时启动完成。
SpringBoot 最后阶段,启动完成Spring 上下文,才开启Http入口流量,此时 SmartLifecycle#start 已执行。所有单例Bean和SpringEvent等组件都已经就绪!
8.项目中在 init-method 方法中注册 Rpc是否合理?什么是时候注册最合理?
init 开启Rpc流量非常不合理。因为Spring尚未启动完成,包括 Spring Event尚未就绪!在SmartInitializingSingleton后
9.项目中在 init-method 方法中注册 MQ消费组是否合理?什么是合理的时机?
init 开启 MQ 流量非常不合理。因为Spring尚未启动完成,包括 Spring Event尚未就绪!在SmartInitializingSingleton后
1.Spring还未完全启动,在 PostConstruct 中调用 getBeanByAnnotation能否获得准确的结果?
虽然未启动完成,但是Spring执行该getBeanByAnnotation方法时,会率先检查 Bean定义,如果Bean定义对应的 Bean尚未初始化,则初始化这些Bean。所以即便是Spring初始化过程中调用,调用结果是准确的。
深入源码
看一下源码中,Spring初始化单例Bean和SmartInitializingSingleton的位置
Autowired何时装配Bean的依赖
在Bean实例化之后,但初始化之前,AutowiredAnnotationBeanPostProcessor 会注入Autowired字段。
SpringBoot何时开启Http端口
SpringBoot会首先启动 Spring上下文,完成后才启动 嵌入式Web容器,初始化SpringMVC,监听端口
SpringBoot初始化Bean的关键代码
AbsractAutowireCapableBeanFactory -->initializeBean()
汇总
SpringBoot 会在Spring完全启动完成后,才开启Http流量。这给了我们启示:应该在Spring启动完成后开启入口流量。
Rpc和 MQ流量 也应该如此,所以建议大家 在 SmartLifecype 或者 ContextRefreshedEvent 等位置 注册服务,开启流量。