Spring Boot的Listener机制的用法和实现原理详解
之前在介绍了在spring-boot启动过程中调用runner的原理,今天我们介绍另外一种可以实现相似功能的机制:spring-boot的Listener机制。
通过注册Listener,可以实现对于spring-boot整个生命周期各个状态变化进行监听,然后执行相应的业务代码。我们只需要监听其中几个启动状态就能够实现runner一样的功能了。
如何使用Spring Boot Listener
要想在spring-boot工程中加入自己实现的Listener,只需要完成一下两步动作:
- 实现SpringApplicationRunListener接口
- 在spring.factories文件中添加上相应的配置
样例代码:

SpringApplicationRunListener实现

spring.factories中的配置
运行结果:

从运行结果我们可以看出:
- 各个状态回调的顺序为:starting->environmentPrepared->contextPrepared->contextLoaded->started->running,再加上一个启动出错时的回调failed
- 每一个状态的回调对应的是spring-boot程序在启动时的不同的阶段,可以利用的spring-boot资源也是不一样的,比如starting状态就无法利用任何spring-boot相关的功能,因为这个时候spring-boot还没有进行任何实际的初始化。
Spring Boot Listener的实现原理
Listener的原理可以总结为:
- 加载SpringApplicationRunListener接口的实现类
- 在spring-boot各个启动阶段调用相应的Listener接口
首先我们来看看SpringApplicationRunListener接口的实现类是怎么被加载起来的。要向了解Listener是如何被加载的,就需要先知道Spring的SPI机制(spring.factories机制),这个我将会在另外一篇文章中介绍。
进入SpringApplication的run方法,我们可以看到如下的一段代码:

加载Listener
在这里就是调用了加载Listener的方法,最终会走到如下的代码中去

在这个方法中主要做了三件事情:
- 利用spring.factories的机制获取了所有SpringApplicationRunListener实现类的类名。
- 根据查找到的类名进行实例化,使用的是带有SpringApplication和String[]两个参数的构造方法。
- 这些SpringApplicationRunListener实例按照order进行排序。
接下来我们再看看Listener是如何被调用的。

调用starting
在Listener被加载完成以后就立马调用starting方法了,这个时候spring-boot实际什么都没有初始化,所以无法使用任何的spring-boot特性。

调用environmentPrepared
调用environmentPrepared

调用contextPrepared和contextLoaded
接下来就会进行context的初始化,在完成context的准备工作后就会调用contextPrepared方法,在完成整个context的初始化工作后就会调用contextLoaded。
started和running都是在run方法中被直接调用的,srping-boot的runner就是在他们之间被调用的。
整个启动过程都是被try-catch包裹着的,任何异常都会进入handleRunFailure方法,在这个方法中会调用Listener的failed方法。
Spring Boot的Listener机制的用法和实现原理详解的更多相关文章
- Spring Boot中对自然语言处理工具包hanlp的调用详解
概 述 HanLP 是基于 Java开发的 NLP工具包,由一系列模型与算法组成,目标是普及自然语言处理在生产环境中的应用.而且 HanLP具备功能完善.性能高效.架构清晰.语料时新.可自定义的特点, ...
- Spring Boot 揭秘与实战 源码分析 - 工作原理剖析
文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...
- Spring Boot干货系列:(三)启动原理解析
Spring Boot干货系列:(三)启动原理解析 2017-03-13 嘟嘟MD 嘟爷java超神学堂 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说 ...
- Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程
上文,我们看了IOC设计要点和设计结构:紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的. ...
- 2017.3.31 spring mvc教程(二)核心流程及配置详解
学习的博客:http://elf8848.iteye.com/blog/875830/ 我项目中所用的版本:4.2.0.博客的时间比较早,11年的,学习的是Spring3 MVC.不知道版本上有没有变 ...
- 整合Spring时Service层为什么不做全局包扫描详解
合Spring时Service层为什么不做全局包扫描详解 一.Spring和SpringMVC的父子容器关系 1.讲问题之前要先明白一个关系 一般来说,我们在整合Spring和SpringMVC这两个 ...
- spring盒springMVC整合父子容器问题:整合Spring时Service层为什么不做全局包扫描详解
整合Spring时Service层为什么不做全局包扫描详解 一.Spring和SpringMVC的父子容器关系 1.讲问题之前要先明白一个关系 一般来说,我们在整合Spring和SpringMVC这两 ...
- Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)
上文,我们看了IOC设计要点和设计结构:以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的:容器中存放的是Bean的定义即Be ...
- ASP.NET MVC 5 学习教程:Edit方法和Edit视图详解
原文 ASP.NET MVC 5 学习教程:Edit方法和Edit视图详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 ...
随机推荐
- Webstorm通用设置
常用快捷键 Ctrl+Alt+L : 格式化代码
- CPU火焰图
y轴:栈深度 x轴:cpu时间 长方形:一个栈(方法) 长度:出现在监视器中的时长(占用cpu的时间) 其他:从左到右的顺序只是按字母排序,无其他意义 火焰图就是看顶层的哪个函数占据的宽度最大.只要有 ...
- mysql与linux ~ 磁盘分析与调优
一 简介 谈谈磁盘IO的问题二 目的:如何进行IO性能问题的排查 二 linux角度 一 机械硬盘基本定义 寻道时间,表示磁头在不同磁道之间移动的时间(最耗时). 旋转延 ...
- 省市联动-获取资源文件xml 获取nodes的方法要学会
try { SAXReader reader = new SAXReader(); InputStream input = this.getClass().getResourceAsStream(&q ...
- 【Udacity并行计算课程笔记】- Lesson 4 Fundamental GPU Algorithms (Applications of Sort and Scan)
I. Scan应用--Compact 在介绍这节之前,首先给定一个情景方便理解,就是因为某种原因我们需要从扑克牌中选出方块的牌. 更formal一点的说法如下,输入是 \(s_0,s_1,...\), ...
- 20165221 JAVA第五周学习心得
课本知识点 内部类与异常类 内部类:在一个类中定义另一个类 特点:外嵌类的成员在内部类仍然有效,内部类也可调用外嵌类的方法,内部类的类体不能声明类变量及类方法 非内部类不能是static类 匿名类:创 ...
- SpringSecurityOAuth认证配置及Token的存储
⒈pom依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- Faster_RCNN 3.模型准备(下)
总结自论文:Faster_RCNN,与Pytorch代码: 本文主要介绍代码第二部分:model/ , 首先分析一些主要理论操作,然后在代码分析里详细介绍其具体实现. 首先在参考文章的基础上进一步详细 ...
- Windows Server 2008 R2忘记密码导致无法修改密码
其实有个记住密码的工具还是简单的,登陆系统后,CMD输入命令: net user administrator NewPassword 新密码即时生效
- VC常用小知识
(1) 如何通过代码获得应用程序主窗口的 指针?主窗口的 指针保存在CWinThread::m_pMainWnd中,调用AfxGetMainWnd实现.AfxGetMainWnd() ->Sho ...