大家都知道,在 Spring 框架中事件和监听无处不在,打通了 Spring 框架的任督二脉,事件和监听也是 Spring 框架必学的核心知识之一。

一般来说,我们很少会使用到应用程序事件,但我们也不要忘了它们的存在,比如说在 Spring 框架内部都使用了各种不同的事件来处理不同的任务。

毫无疑问,在 Spring Boot 框架中,事件和监听也得到了发扬光大,除了常用的 Spring Framework 事件(例如:ContextRefreshedEvent)之外,Spring Boot 在启动过程中还发送一系列其他的应用程序事件。

Spring Boot 启动事件顺序

1、ApplicationStartingEvent

这个事件在 Spring Boot 应用运行开始时,且进行任何处理之前发送(除了监听器和初始化器注册之外)。

2、ApplicationEnvironmentPreparedEvent

这个事件在当已知要在上下文中使用 Spring 环境(Environment)时,在 Spring 上下文(context)创建之前发送。

3、ApplicationContextInitializedEvent

这个事件在当 Spring 应用上下文(ApplicationContext)准备好了,并且应用初始化器(ApplicationContextInitializers)已经被调用,在 bean 的定义(bean definitions)被加载之前发送。

4、ApplicationPreparedEvent

这个事件是在 Spring 上下文(context)刷新之前,且在 bean 的定义(bean definitions)被加载之后发送。

5、ApplicationStartedEvent

这个事件是在 Spring 上下文(context)刷新之后,且在 application/ command-line runners 被调用之前发送。

6、AvailabilityChangeEvent

这个事件紧随上个事件之后发送,状态:ReadinessState.CORRECT,表示应用已处于活动状态。

7、ApplicationReadyEvent

这个事件在任何 application/ command-line runners 调用之后发送。

8、AvailabilityChangeEvent

这个事件紧随上个事件之后发送,状态:ReadinessState.ACCEPTING_TRAFFIC,表示应用可以开始准备接收请求了。

9、ApplicationFailedEvent

这个事件在应用启动异常时进行发送。


上面所介绍的这些事件列表仅包括绑定到 SpringApplication 的 SpringApplicationEvents 事件,除了这些事件以外,以下事件也会在 ApplicationPreparedEvent 之后和 ApplicationStartedEvent 之前发送:

  • WebServerInitializedEvent

    这个 Web 服务器初始化事件在 WebServer 启动之后发送,对应的还有 ServletWebServerInitializedEvent(Servlet Web 服务器初始化事件)、ReactiveWebServerInitializedEvent(响应式 Web 服务器初始化事件)。

  • ContextRefreshedEvent

    这个上下文刷新事件是在 Spring 应用上下文(ApplicationContext)刷新之后发送。


自定义启动事件监听器

既然我们知道了 Spring Boot 在启动过程中的各个事件,那么我们就可以在每个环节来处理一些我们想做的事情,只需要自定义一个监听器来监听某个事件就可以了。

比如我们想在上面的第 8 步,即应用启动完成可以接收请求了,我们简单输出一个成功标识。

Spring Boot 基础的构建这里就不介绍了,如果你对 Spring Boot 还不是很熟悉,或者只是会简单的使用,那还是建议你深入学习下吧,推荐这个 Spring Boot 学习仓库,欢迎 Star 关注:

https://github.com/javastacks/spring-boot-best-practice

1、新建监听器

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.availability.ReadinessState;
import org.springframework.context.ApplicationListener; /**
* 来源微信公众号:Java技术栈
*/
@Slf4j
public class JavastackListener implements ApplicationListener<AvailabilityChangeEvent> { @Override
public void onApplicationEvent(AvailabilityChangeEvent event) {
log.info("监听到事件:" + event);
if (ReadinessState.ACCEPTING_TRAFFIC == event.getState()){
log.info("应用启动完成,可以请求了……");
}
} }

新建一个自定义监听器,实现了 ApplicationListener 接口,泛型 AvailabilityChangeEvent 表示仅仅监听 AvailabilityChangeEvent 事件。

因第 8 步的事件和第 6 步的事件同名,我们可以根据事件的状态来区分到底是哪一个环节的事件 。

2、注册监听器

注册监听器有两种方式:

1、在资源目录中的 META-INF/spring.factories 文件中自动注册:

org.springframework.context.ApplicationListener=\
cn.javastack.springboot.features.listener.JavastackListener

2、如果是监听 Spring 应用上下文(ApplicationContext)创建之后的事件,可以直接在监听器上使用 @Component 注解即可,否则需要使用第一种方法的自动注册,因为 ApplicationContext 并未创建,这时的 Bean 是不能被加载的。

3、应用启动

下面来看下启动日志:

可以看到同时输出了第 6 步和 8 步的监听日志,但只输出第 8 步的启动完成日志,自定义监听实现成功。

总结

了解了 Spring Boot 启动过程中的各个事件及监听机制,大家可以依葫芦画瓢实现 Spring Boot 启动过程中的各个自定义操作,比如说在启动过程上实现动态注册、移除 Bean 等。

一般来说,不建议使用事件和监听器来实现比较耗时和繁重的任务,这样会影响应用程序的正常启动,考虑使用 Spring Boot 的 application/ command-line runners 来进行实现。

本文只是介绍了一下 Spring Boot 启动过程中的事件及如何实现自定义监听器,怎么实现一个业务上的自定义事件和监听器不在本文范围之类,后续栈长再开一篇,关注公众号Java技术栈第一时间推送,不要走开。

本文实践所有源代码已上传:

https://github.com/javastacks/spring-boot-best-practice

参考资料:

https://docs.spring.io/spring-boot/docs/2.3.5.RELEASE/reference/htmlsingle/#boot-features-application-events-and-listeners

最后,觉得有收获,在看、转发一下哦,原创不易,需要鼓励。

版权申明:本文系公众号 "Java技术栈" 原创,原创实属不易,转载、引用本文内容请注明出处,禁止抄袭、洗稿,请自重,尊重他人劳动成果和知识产权。

近期热文推荐:

1.Java 15 正式发布, 14 个新特性,刷新你的认知!!

2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香!

3.我用 Java 8 写了一段逻辑,同事直呼看不懂,你试试看。。

4.吊打 Tomcat ,Undertow 性能很炸!!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!

Spring Boot 启动事件和监听器,太强大了!的更多相关文章

  1. Spring Boot Application 事件和监听器

    https://www.cnblogs.com/fdzfd/p/7872909.html ***************************************************** 一 ...

  2. [Spring Boot] Spring Boot启动过程源码分析

    关于Spring Boot,已经有很多介绍其如何使用的文章了,本文从源代码(基于Spring-boot 1.5.6)的角度来看看Spring Boot的启动过程到底是怎么样的,为何以往纷繁复杂的配置到 ...

  3. Spring Boot启动过程源码分析--转

    https://blog.csdn.net/dm_vincent/article/details/76735888 关于Spring Boot,已经有很多介绍其如何使用的文章了,本文从源代码(基于Sp ...

  4. Spring Boot启动过程(四):Spring Boot内嵌Tomcat启动

    之前在Spring Boot启动过程(二)提到过createEmbeddedServletContainer创建了内嵌的Servlet容器,我用的是默认的Tomcat. private void cr ...

  5. Spring Boot启动过程(七):Connector初始化

    Connector实例的创建已经在Spring Boot启动过程(四):Spring Boot内嵌Tomcat启动中提到了: Connector是LifecycleMBeanBase的子类,先是设置L ...

  6. Spring Boot 启动(二) Environment 加载

    Spring Boot 启动(二) Environment 加载 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 上一节中 ...

  7. Spring Boot 启动(一) SpringApplication 分析

    Spring Boot 启动(一) SpringApplication 分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html ...

  8. Spring Boot实践——事件监听

    借鉴:https://blog.csdn.net/Harry_ZH_Wang/article/details/79691994 https://blog.csdn.net/ignorewho/arti ...

  9. Spring Boot启动流程分析

    引言 早在15年的时候就开始用spring boot进行开发了,然而一直就只是用用,并没有深入去了解spring boot是以什么原理怎样工作的,说来也惭愧.今天让我们从spring boot启动开始 ...

随机推荐

  1. kubernetes个人笔记(一)

    一.证书工具 CFSSL keytools,openssl 1.介绍 CFSSL is CloudFlare's PKI/TLS swiss army knife. It is both a comm ...

  2. javascript布局转换

    javascript布局转换是将原有的浮动布局通过JS里面的javascript属性 offsetLeft 和offsetTop默认值来给元素设置绝对定位. 原来的:缺点--我们想给网页中的图片添加拖 ...

  3. 深度分析:面试阿里,字节99%会被问到Java类加载机制和类加载器

    1. 类加载机制 所谓类加载机制就是JVM虚拟机把Class文件加载到内存,并对数据进行校验,转换解析和初始化,形成虚拟机可以直接使用的Jav类型,即Java.lang.Class. 2. 类加载的过 ...

  4. 在FL Studio中如何使用Patcher插件

    Patcher作为FL Studio20中自由度极高的一款插件,深受当今制作人的喜爱.其主要功能用于整合混音插件的输入与输出以及自定义控制器等功能.下面分几部分来介绍这个插件. Patcher的Map ...

  5. 在FL Studio编曲软件中查找采样的音高

    相信玩音乐的小伙伴们都遇到过这种情况,在用FL Studio编曲时,想添加一段音频采样,由于采样的调式与我们正在编曲的调式不同,音频之间的衔接就是一个非常头疼的问题,要解决采样的调式,我们就得先确认这 ...

  6. 「CSP-S 2019」划分

    description loj 3212 solution 首先容易想到\(n^3\)DP,即令\(f_{i,j}\)表示前\(i\)个数的划分,其中最后一段是从\(j\)开始时的答案 于是有 \[f ...

  7. python中操作数据库

    python中要操作数据库,要使用该数据库在python中对应的驱动库,本文介绍python操作mysql数据库 1.首先安装pymysql 2.导入库 3.建立连接 4.建立游标 5.发起请求 6. ...

  8. yii2.0 ActiveForm 单选框与复选框使用

    yii2.0 中的ActiveForm 复选框的使用 默认的复选框选项为纵向的<?= $form->field($model, 'line')->checkboxList(Pictu ...

  9. docker私有云管理平台-----shipyard

    下载所需docker镜像 docker pull rethinkdb docker pull microbox/etcd docker pull shipyard/docker-proxy docke ...

  10. [GIT]获取git最新的tag

    背景 公司前端项目在Jenkins中打包,每次打包需要将新tag回推到仓库中.但是打包失败后如果不删除tag的话下次打包就会失败,需要手动删除,所以在Jenkinsfile中就需要在打包失败时自动删除 ...