spring boot 之监听器ApplicationListener
监听器
ApplicationListener 就是spring的监听器,能够用来监听事件,典型的观察者模式。
ApplicationListener和ContextRefreshedEvent一般都是成对出现的
在IOC容器的启动过程中,当所有的bean都已经处理完成之后,spring ioc容器会有一个发布事件的动作。从AbstractApplicationContext 的源码中可以看出:
/**
* Finish the refresh of this context, invoking the LifecycleProcessor's
* onRefresh() method and publishing the
* {@link org.springframework.context.event.ContextRefreshedEvent}.
*/
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches(); // Initialize lifecycle processor for this context.
initLifecycleProcessor(); // Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh(); // Publish the final event.
publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
这样,当ioc容器加载处理完相应的bean之后,也给我们提供了一个机会(先有InitializingBean,后有ApplicationListener<ContextRefreshedEvent>),可以去做一些自己想做的事。其实这也就是spring ioc容器给提供的一个扩展的地方。我们可以这样使用这个扩展机制。
一个最简单的方式就是,让我们的bean实现ApplicationListener接口,这样当发布事件时,spring 的ioc容器就会以容器的实例对象作为事件源类,并从中找到事件的监听者,此时ApplicationListener接口实例中的onApplicationEvent(E event)方法就会被调用,我们的逻辑代码就会写在此处。这样我们的目的就达到了。但这也带来一个思考,有人可能会想,这样的代码我们也可以通过实现spring 的InitializingBean接口来实现啊,也会被spring 容器去自动调用,但是大家应该想到,如果我们现在想做的事,是必须要等到所有的bean都被处理完成之后再进行,此时InitializingBean接口的实现就不合适了,所以需要深刻理解事件机制的应用场合。
系统会存在两个容器,一个是root application context ,另一个就是我们自己的 projectName-servlet context(作为root application context的子容器)
这种情况下,就会造成onApplicationEvent方法被执行两次。为了避免上面提到的问题,我们可以只在root application context初始化完成后调用逻辑代码,其他的容器的初始化完成,则不做任何处理
简单示例代码如下:
package com.example.demo.init; import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component; @Component
public class ZkServerInit implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent context) {
if (null == context.getApplicationContext().getParent()) {
System.err.println("初始化zkServer...");
// 初始化逻辑...
System.err.println("初始化zkServer完成...");
}
}
}
spring boot 之监听器ApplicationListener的更多相关文章
- Spring Boot使用监听器Listener
之前介绍了在Spring Boot中使用过滤器:https://www.cnblogs.com/zifeiy/p/9911056.html 接下来介绍使用监听器Listener. 下面是一个例子: p ...
- Spring Boot 整合监听器
Listener是servlet规范中定义的一种特殊类,用于监听servletContext.HttpSession和servletRequest等域对象的创建和销毁事件,监听域对象的属性发生修改的事 ...
- spring boot到底帮我们做了那些事?
一.前言 上一篇介绍了注解,也是为这一篇做铺垫,传统的都是通过配置文件来启动spring,那spring boot到底是做了什么能让我们快速开发昵? 二.启动原理 看下程序启动的入口, ...
- Spring Boot SpringApplication启动类(二)
目录 前言 1.起源 2.SpringApplication 运行阶段 2.1 SpringApplicationRunListeners 结构 2.1.1 SpringApplicationRunL ...
- Spring Boot系列(四) Spring Cloud 之 Config Client
Config 是通过 PropertySource 提供. 这节的内容主要是探讨配置, 特别是 PropertySource 的加载机制. Spring Cloud 技术体系 分布式配置 服务注册/发 ...
- 精尽Spring Boot源码分析 - 日志系统
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- Spring Boot 外部化配置(一)- Environment、ConfigFileApplicationListener
目录 前言 1.起源 2.外部化配置的资源类型 3.外部化配置的核心 3.1 Environment 3.1.1.ConfigFileApplicationListener 3.1.2.关联 Spri ...
- 009-Spring Boot 事件监听、监听器配置与方式、spring、Spring boot内置事件
一.概念 1.事件监听的流程 步骤一.自定义事件,一般是继承ApplicationEvent抽象类 步骤二.定义事件监听器,一般是实现ApplicationListener接口 步骤三.启动时,需要将 ...
- Spring监听器---ApplicationListener
说到事件监听,想到的肯定是观察者模式.但是这儿主要说下spring中的监听是怎么样的流程. 这就不得不说到spring容器的refresh方法,容器启动过程中,listener相关的主要是这个三个方法 ...
随机推荐
- Go 日常开发常备第三方库和工具
不知不觉写 Go 已经快一年了,上线了大大小小好几个项目:心态也经历了几轮变化. 因为我个人大概前五年时间写的是 Java ,中途写过一年多的 Python,所以刚接触到 Go 时的感觉如下图: 既没 ...
- 一步一步学ROP之linux_x64篇(蒸米spark)
目录 一步一步学ROP之linux_x64篇(蒸米spark) 0x00 序 0x01 Memory Leak & DynELF - 在不获取目标libc.so的情况下进行ROP攻击 0x02 ...
- 用python写一个自动化盲注脚本
前言 当我们进行SQL注入攻击时,当发现无法进行union注入或者报错等注入,那么,就需要考虑盲注了,当我们进行盲注时,需要通过页面的反馈(布尔盲注)或者相应时间(时间盲注),来一个字符一个字符的进行 ...
- 第一篇:《Kubernetes 入门介绍》
前言:本文是一篇 kubernetes(下文用 k8s 代替)的入门文章,将会涉及 k8s 的技术历史背景.架构.集群搭建.一个 Redis 的例子,以及如何使用 operator-sdk 开发 op ...
- c++ IO库
1:为了支持使用宽字符的语言,标准库定义了一组类型和对象来操作wchar_t类型的数据.宽字符版本的类型和函数的名字以w开头.宽字符版本和普通的char版本定义在同一个头文件中,例如头文件fstrea ...
- jenkins 安装与使用
1.jenkins下载:https://jenkins.io/zh/download/ 2.将下载好的war包放到tomcat容器下的D:\apache-tomcat-9.0.10\webapps下( ...
- 高德地图API中折线polyline不能跨越180度经度线的解决方案
1.问题 最近在使用高德地图的API,有一个需求是画出对象的历史轨迹,采用了高德地图API中的折线polyline函数.但如果需要跨180度经度线的折线,会出现不能跨越的情况,如下图所示: 图中有三个 ...
- Python基础(序列化)
#pickling import pickle,json # d = dict(name='傻狗1',age=300,score=100) # d1 = pickle.dumps(d)#pickle. ...
- vue + cesium开发(5) 搭建 vue + cesium开发环境(2)
上vue+cesium开发(1)中,没有进行配置webpack,而是使用了插件进行代替,在使用过程中出现了一些未知BUG,影响体验,因此参考了官方文档对项目进行重新配置,使用了 copy-webpac ...
- Dapr-Actor构建块
前言: 前篇-绑定 文章对Dapr的绑定构建块进行了解,本篇继续对 Actor 构建块进行了解学习. 一.Actor简介: Actors 为最低级别的"计算单元". 换句话说,您将 ...