今天继续来聊Spring Boot 2.0的新特性。本文将具体说说2.0版本中的事件模型,尤其是新增的事件: ApplicationStartedEvent

原文首发:http://blog.didispace.com/Spring-Boot-2-0-feature-2-ApplicationStartedEvent/

在Spring Boot 2.0中对事件模型做了一些增强,主要就是增加了 ApplicationStartedEvent事件,所以在2.0版本中所有的事件按执行的先后顺序如下:

  • ApplicationStartingEvent

  • ApplicationEnvironmentPreparedEvent

  • ApplicationPreparedEvent

  • ApplicationStartedEvent <= 新增的事件

  • ApplicationReadyEvent

  • ApplicationFailedEvent

从上面的列表中,我们可以看到 ApplicationStartedEvent位于 ApplicationPreparedEvent之后, ApplicationReadyEvent之前。

下面我们通过代码的方式来直观的感受这个事件的切入位置,以便与将来我们在这个切入点加入自己需要的逻辑。

第一步:我们可以编写 ApplicationPreparedEventApplicationStartedEvent以及 ApplicationReadyEvent三个事件的监听器,然后在这三个事件触发的时候打印一些日志来观察它们各自的切入点,比如:


  1. @Slf4j

  2. public class ApplicationPreparedEventListener implements ApplicationListener<ApplicationPreparedEvent> {

  3. @Override

  4. public void onApplicationEvent(ApplicationPreparedEvent event) {

  5. log.info("......ApplicationPreparedEvent......");

  6. }

  7. }

  8. @Slf4j

  9. public class ApplicationStartedEventListener implements ApplicationListener<ApplicationStartedEvent> {

  10. @Override

  11. public void onApplicationEvent(ApplicationStartedEvent event) {

  12. log.info("......ApplicationStartedEvent......");

  13. }

  14. }

  15. @Slf4j

  16. public class ApplicationReadyEventListener implements ApplicationListener<ApplicationReadyEvent> {

  17. @Override

  18. public void onApplicationEvent(ApplicationReadyEvent event) {

  19. log.info("......ApplicationReadyEvent......");

  20. }

  21. }

第二步:在 /src/main/resources/目录下新建: META-INF/spring.factories配置文件,通过配置 org.springframework.context.ApplicationListener来加载上面我们编写的监听器。


  1. org.springframework.context.ApplicationListener=

  2. com.didispace.ApplicationPreparedEventListener,\

  3. com.didispace.ApplicationReadyEventListener,\

  4. com.didispace.ApplicationStartedEventListener

此时,我们运行Spring Boot应用可以获得类似如下日志输出:


  1. 2018-03-07 18:15:18.591 INFO 83387 --- [ main] com.didispace.Application : Starting Application on zhaiyongchaodeMacBook-Pro.local with PID 83387 (/Users/zhaiyongchao/Documents/git/github/SpringBoot-Learning/Chapter1-2-1/target/classes started by zhaiyongchao in /Users/zhaiyongchao/Documents/git/github/SpringBoot-Learning/Chapter1-2-1)

  2. 2018-03-07 18:15:18.591 INFO 83387 --- [ main] com.didispace.Application : No active profile set, falling back to default profiles: default

  3. 2018-03-07 18:15:18.658 INFO 83387 --- [ main] c.d.ApplicationPreparedEventListener : ......ApplicationPreparedEvent......

  4. 2018-03-07 18:15:18.662 INFO 83387 --- [ main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@20d3d15a: startup date [Wed Mar 07 18:15:18 CST 2018]; root of context hierarchy

  5. 2018-03-07 18:15:19.879 INFO 83387 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)

  6. 2018-03-07 18:15:19.926 INFO 83387 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]

  7. 2018-03-07 18:15:19.930 INFO 83387 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.28

  8. 2018-03-07 18:15:19.946 INFO 83387 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/zhaiyongchao/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]

  9. 2018-03-07 18:15:20.068 INFO 83387 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext

  10. 2018-03-07 18:15:20.068 INFO 83387 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1410 ms

  11. 2018-03-07 18:15:20.210 INFO 83387 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet dispatcherServlet mapped to [/]

  12. 2018-03-07 18:15:20.214 INFO 83387 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]

  13. 2018-03-07 18:15:20.214 INFO 83387 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]

  14. 2018-03-07 18:15:20.214 INFO 83387 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]

  15. 2018-03-07 18:15:20.215 INFO 83387 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]

  16. 2018-03-07 18:15:20.513 INFO 83387 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@20d3d15a: startup date [Wed Mar 07 18:15:18 CST 2018]; root of context hierarchy

  17. 2018-03-07 18:15:20.592 INFO 83387 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)

  18. 2018-03-07 18:15:20.593 INFO 83387 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)

  19. 2018-03-07 18:15:20.623 INFO 83387 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]

  20. 2018-03-07 18:15:20.623 INFO 83387 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]

  21. 2018-03-07 18:15:20.660 INFO 83387 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]

  22. 2018-03-07 18:15:20.787 INFO 83387 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup

  23. 2018-03-07 18:15:20.839 INFO 83387 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''

  24. 2018-03-07 18:15:20.843 INFO 83387 --- [ main] com.didispace.Application : Started Application in 2.866 seconds (JVM running for 3.337)

  25. 2018-03-07 18:15:20.845 INFO 83387 --- [ main] c.d.ApplicationStartedEventListener : ......ApplicationStartedEvent......

  26. 2018-03-07 18:15:20.847 INFO 83387 --- [ main] c.d.ApplicationReadyEventListener : ......ApplicationReadyEvent......

从日志中我们可以看到清晰的看到 ApplicationPreparedEventApplicationStartedEvent以及 ApplicationReadyEvent三个事件的切入点。通过这个例子可能读者会感到疑问: ApplicationStartedEventApplicationReadyEvent从事件命名和日志输出位置来看,都是应用加载完成之后的事件,它们是否有什么区别呢?

下面可以看看官方文档对 ApplicationStartedEventApplicationReadyEvent的解释:

An ApplicationStartedEvent is sent after the context has been refreshed but before any application and command-line runners have been called.An ApplicationReadyEvent is sent after any application and command-line runners have been called. It indicates that the application is ready to service requests

从文档中我们可以知道他们两中间还有一个过程就是 command-line runners被调用的内容。所以,为了更准确的感受这两个事件的区别,我们在应用主类中加入 CommandLineRunner的实现,比如:


  1. @Slf4j

  2. @SpringBootApplication

  3. public class Application {

  4. public static void main(String[] args) {

  5. SpringApplication.run(Application.class, args);

  6. }

  7. @Bean

  8. public DataLoader dataLoader() {

  9. return new DataLoader();

  10. }

  11. @Slf4j

  12. static class DataLoader implements CommandLineRunner {

  13. @Override

  14. public void run(String... strings) throws Exception {

  15. log.info("Loading data...");

  16. }

  17. }

  18. }

最后,我们再运行程序,此时我们可以发现这两个事件中间输出了上面定义的 DataLoader的输出内容,具体如下:


  1. 2018-03-07 18:15:20.845 INFO 83387 --- [main] c.d.ApplicationStartedEventListener : ......ApplicationStartedEvent......

  2. 2018-03-07 18:15:20.846 INFO 83387 --- [main] com.didispace.Application$DataLoader : Loading data...

  3. 2018-03-07 18:15:20.847 INFO 83387 --- [main] c.d.ApplicationReadyEventListener : ......ApplicationReadyEvent......

推荐阅读

  • Spring Boot 2.0 新特性(一):配置绑定 2.0 全解析

  • Spring Boot 2.0正式发布,升还是不升呢?

  • Spring Boot 2.0 新特性概览

  • Spring Boot/Cloud干货汇总

  • Spring Cloud Gateway真的有那么差吗?

代码示例

本文的相关例子可以查看下面仓库中的 Chapter1-2-1目录:

  • Github:https://github.com/dyc87112/SpringBoot-Learning

  • Gitee:https://gitee.com/didispace/SpringBoot-Learning

【真】Spring Booot 2.0 新特性详解正在连载!!!

长按指纹

一键关注



深入交流、更多福利

扫码加入我的知识星球


点击 “阅读原文” 看看本号其他精彩内容

Spring Boot 2.0 新特性(二):新增事件ApplicationStartedEvent相关推荐

  1. Spring Boot 2.0 新特性(一):配置绑定 2.0 全解析

    在Spring Boot 2.0中推出了Relaxed Binding 2.0,对原有的属性绑定功能做了非常多的改进以帮助我们更容易的在Spring应用中加载和读取配置信息.下面本文就来说说Sprin ...

  2. Spring Boot 2.0 新特性

    作者:贺卓凡 原文:https://mp.weixin.qq.com/s/EWmuzsgHueHcSB0WH-3AQw 以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8 ...

  3. Spring Boot 2.0 新特性和发展方向

    以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...

  4. Spring Boot 2.0新特性

    Spring Boot依赖于Spring,而Spring Cloud又依赖于Spring Boot,因此Spring Boot2.0的发布正式整合了Spring5.0的很多特性,同样后面Spring ...

  5. 03-Spring Boot 2.0 新特性详解

    背景 在 3 月 1 号,Spring Boot2.0.0.RELEASE正式发布,这是 Spring Boot1.0 发布 4 年之后第一次重大修订,因此有多的新功能和特性值得大家期待!下面带大家了 ...

  6. Spring Boot 2.x 新特性总结及迁移指南

    这一篇文章主要讲解 Spring Boot 2.x 与 1.5.x 的区别,2.x 主要更新了什么东西,以便对 Spring Boot 2.x 有一个详细的了解. 本文讲的 1.x 指的是 1.5.1 ...

  7. Spring Boot学习总结(24)——Spring Boot 2.5 新特性一览

    前言 距离上次的 Spring Boot 2.4.5 版本发布刚好一个月左右,Spring Boot 又发新版本了! Spring Boot 又一次性发布了 3 个版本: Spring Boot 2. ...

  8. Spring学习总结(23)——Spring Framework 5.0 新特性

    Spring Framework 5.0 是自 2013年12月版本 4 发布之后 Spring Framework 的第一个主发行版.Spring Framework 项目的领导人 Juergen ...

  9. Java8.0 新特性二之Stream

    Stream流 概述 说道Stream便容易想到I/O Stream, 而实际上,谁规定"流" 就一定是"IO流"呢?在Java8中,得益于Lambda所带来的 ...

最新文章

  1. MegEngine 框架设计
  2. discuz云平台报调用远程接口失败的问题分析和解决
  3. 11条javascript知识
  4. 弹性文件服务解密 -- 应用场景区分
  5. MathType中公式不对齐怎么办
  6. 【风电功率预测】基于matlab遗传算法优化BP神经网络风电功率预测【含Matlab源码 760期】
  7. 第二章 人工智能专题之Python进阶 - Matplotlib库
  8. CronTrigger(重要,非常强大)
  9. 都有哪些较好用的项目管理软件?
  10. android手机home键,手机Home键在哪里?手机Home键是什么意思?
  11. 北航大学计算机教学平台,信息学院赴北京航空航天大学计算机教学实验中心参观交流...
  12. python 文件名变量_如何将变量文件名传递给python ete?
  13. iframe框架下的子父级页面监控页面关闭事件
  14. Invalid byte tag in constant pool: 18
  15. Materials Studio8.0
  16. 0-1背包问题(0-1 knapsack problem)c++实现
  17. 不超过十个人的好电影
  18. 计算机毕业设计ssm双峰县在线房屋租售网站
  19. C++ 打怪小游戏3.1
  20. 2020年中国矿业大学调剂信息:人工智能与信号处理方向(控制科学与工程专业)...

热门文章

  1. linux 安装软件出现/tmp 磁盘不足时 解决方案
  2. ActiveMQ activemq web管理界面介绍
  3. linux tar 提示 time stamp xxx in the future 解决方法
  4. linux upx 报错 NotCompressibleException
  5. mysql order by 多字段排序
  6. javascript jquery 获取select选中的值
  7. centos7 安装 python3
  8. ClamAV病毒库增加特征码
  9. curl 视频vip接口 php,php中CURL的使用方法及详解教程
  10. 监视mysql 哪些指标_MySQL 监控指标