监听器
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的更多相关文章

  1. Spring Boot使用监听器Listener

    之前介绍了在Spring Boot中使用过滤器:https://www.cnblogs.com/zifeiy/p/9911056.html 接下来介绍使用监听器Listener. 下面是一个例子: p ...

  2. Spring Boot 整合监听器

    Listener是servlet规范中定义的一种特殊类,用于监听servletContext.HttpSession和servletRequest等域对象的创建和销毁事件,监听域对象的属性发生修改的事 ...

  3. spring boot到底帮我们做了那些事?

    一.前言     上一篇介绍了注解,也是为这一篇做铺垫,传统的都是通过配置文件来启动spring,那spring boot到底是做了什么能让我们快速开发昵? 二.启动原理     看下程序启动的入口, ...

  4. Spring Boot SpringApplication启动类(二)

    目录 前言 1.起源 2.SpringApplication 运行阶段 2.1 SpringApplicationRunListeners 结构 2.1.1 SpringApplicationRunL ...

  5. Spring Boot系列(四) Spring Cloud 之 Config Client

    Config 是通过 PropertySource 提供. 这节的内容主要是探讨配置, 特别是 PropertySource 的加载机制. Spring Cloud 技术体系 分布式配置 服务注册/发 ...

  6. 精尽Spring Boot源码分析 - 日志系统

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  7. Spring Boot 外部化配置(一)- Environment、ConfigFileApplicationListener

    目录 前言 1.起源 2.外部化配置的资源类型 3.外部化配置的核心 3.1 Environment 3.1.1.ConfigFileApplicationListener 3.1.2.关联 Spri ...

  8. 009-Spring Boot 事件监听、监听器配置与方式、spring、Spring boot内置事件

    一.概念 1.事件监听的流程 步骤一.自定义事件,一般是继承ApplicationEvent抽象类 步骤二.定义事件监听器,一般是实现ApplicationListener接口 步骤三.启动时,需要将 ...

  9. Spring监听器---ApplicationListener

    说到事件监听,想到的肯定是观察者模式.但是这儿主要说下spring中的监听是怎么样的流程. 这就不得不说到spring容器的refresh方法,容器启动过程中,listener相关的主要是这个三个方法 ...

随机推荐

  1. 第04课 OpenGL 旋转

    旋转: 在这一课里,我将教会你如何旋转三角形和四边形.左图中的三角形沿Y轴旋转,四边形沿着X轴旋转. 上一课中我教给您三角形和四边形的着色.这一课我将教您如何将这些彩色对象绕着坐标轴旋转.其实只需在上 ...

  2. zabbix 监控redis 挂掉自动重启 并发送企业微信

    1.创建redis监控项[配置]-[主机]-[监控项]-创建监控项,监控6379端口(注意关闭防火墙或者开启防火墙端口6379) redis配置文件设置允许任何地址监听: 添加监控项 2.创建redi ...

  3. Oracle的主要组件和基本概念

    oracle 简介 oracle(甲骨文)公司 1977年,三人合伙创办(Software Development Laboratories,SDL) 1979年,更名为Relational Soft ...

  4. VC练习一

    1 #include<windows.h> 2 #include<stdio.h> 3 LRESULT CALLBACK WinSunProc(HWND hwnd,UINT u ...

  5. [loj3528]位移寄存器

    当$s=0$时(求最小值): 若$x_{0},x_{1},...,x_{n-1}$和$y_{0},y_{1},...,y_{n-1}$像题中所给的方式存储在$r[0][0..nk-1]$和$r[1][ ...

  6. [bzoj3123]森林

    首先对于询问操作可以使用可持久化线段树来维护,对于连边操作对于两颗树中选取较小的树暴力练到另一个点上,点数可以用并查集然后只修改根的点数即可. 1 #include<bits/stdc++.h& ...

  7. FastAPI(六十二)实战开发《在线课程学习系统》需求分析

    前言 基础的分享我们已经分享了六十篇,那么我们这次分享开始将用一系列的文章分享实战课程.我们分享的系统是在线学习系统.我们会分成不同的模块进行分享.我们的目的是带着大家去用fastapi去实战一次,开 ...

  8. BombEnemy(炸弹人)

    // // Created by Administrator on 2021/7/25. // #ifndef C__TEST01_BOMBENEMY_HPP #define C__TEST01_BO ...

  9. QQ 表情大全

    rt,以下是比较常用的 QQ 表情简写: /kk:快哭了 /cy:呲牙 /ll:流泪 /dk:大哭 /yiw:疑问 /jk:惊恐 /se:色 /kel:可怜 /xyx:斜眼笑 /wx:微笑 /xk:笑 ...

  10. CF1290E Cartesian Tree

    考虑笛卡尔树的意义: 一个点在笛卡尔树中的子树,代表以他为最小/最大值的区间. 所以一个点的子树大小,一定是类似到达序列边界或者被一个比他更大的数隔离. 考虑记录 \(l_i,r_i\) 为第 \(i ...