ApplicationStartedEvent:应用成功启动
@since 2.0.0。截止到此,应用已经准备就绪,并且通过监听器、初始化器等完成了非常多的工作了,但仍旧剩下被认为最为重要的初始化单例Bean动作还没做、web容器(如Tomcat)还没启动,这便是这个周期所要做的事。
完成的大事记
- 启动Spring容器:AbstractApplicationContext#refresh(),这个步骤会做很多事,比如会实例化单例Bean
- 该步骤属于Spring Framework的核心内容范畴,做了很多事,请参考Spring核心技术内容章节
- 在Spring容器refresh()启动完成后,WebServer也随之完成启动,成功监听到对应端口(们)
- 输出启动成功的日志:Started Application in xxx seconds (JVM running for xxx)
- 发送ApplicationStartedEvent事件,触发对应的监听器的执行
- callRunners():依次执行容器内配置的ApplicationRunner/CommandLineRunner的Bean实现类,支持sort排序
- ApplicationRunner:@since 1.3.0,入参是ApplicationArguments,先执行(推荐使用)
- CommandLineRunner:@since 1.0.0,入参是String... args,后执行(不推荐使用)
监听此事件的监听器们
默认情况下,有3个监听器监听ApplicationStartedEvent事件:
- 前两个不用再解释了吧:本事件达到时无动作
- TomcatMetricsBinder:@since 2.1.0。和监控相关:将你的tomcat指标信息TomcatMetrics绑定到MeterRegistry,从而就能收集到相关指标了
总结:此事件节点结束时,SpringApplication的生命周期到这一步,正常的启动流程就全部完成了。也就说Spring Boot应用可以正常对对外提供服务了。
ApplicationReadyEvent:应用已准备好
@since 1.3.0。该事件所处的生命周期可认为基本同ApplicationStartedEvent,仅是在其后执行而已,两者中间并无其它特别的动作,但是监听此事件的监听器们还是蛮重要的。
完成的大事记
同上。
监听此事件的监听器们
默认情况下,有4个监听器监听ApplicationStartedEvent事件:
- SpringApplicationAdminMXBeanRegistrar:当此事件到达时,告诉Admin Spring应用已经ready,可以使用啦。
- 中间这两个不用再解释了吧:本事件达到时无动作
- RefreshEventListener:当此事件到达时,告诉Spring应用已经ready了,接下来便可以执行ContextRefresher.refresh()喽
总结:此事件节点结束时,应用已经完完全全的准备好了,并且也已经完成了相关组件的周知工作。
异常情况
SpringApplication是有可能在启动的时候失败(如端口号已被占用),当然任何一步骤遇到异常时交给SpringApplication#handleRunFailure()方法来处理,这时候也会有对应的事件发出。
ApplicationFailedEvent:应用启动失败
当SpringApplication在启动时抛出异常:可能是端口绑定、也可能是你自定义的监听器你写了个bug等,就会“可能”发送此事件。
完成的大事记
- 得到异常的退出码ExitCode,然后发送ExitCodeEvent事件(非生命周期事件)
- 发送ApplicationFailedEvent事件,触发对应的监听器的执行
监听此事件的监听器们
默认情况下,有6个监听器监听ApplicationStartedEvent事件:
- LoggingApplicationListener:执行loggingSystem.cleanUp()清理资源
- ClasspathLoggingApplicationListener:输出一句debug日志:Application failed to start with classpath: ...
- 中间这两个不用再解释了吧:本事件达到时无动作
- ConditionEvaluationReportLoggingListener:自动配置输出报告,输出错误日志呗:特别方便你查看和错误定位
- 不得不夸:SB对错误定位这块才真叫智能,比Spring Framework好用太多了
- BootstrapApplicationListener.CloseContextOnFailureApplicationListener:执行context.close()
总结:此事件节点结束时,会做一些释放资源的操作。一般情况下:我们并不需要监听到此事件
总结
关于SpringApplication的生命周期体系的介绍就到这了,相信通过此“万字长文”你能体会到A哥的用心。翻了翻市面上的相关文章,本文Almost可以保证是总结得最到位的,让你通过一文便可从大的方面基本掌握Spring Boot,这不管是你使用SB,还是后续自行扩展、精雕细琢SB,以及去深入了解Spring Cloud均由非常重要的意义,希望对你有帮助,谢谢你的三连。