我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Spring事件发布与监听怎么实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Spring事件发布与监听怎么实现

这篇文章主要讲解了“Spring事件发布与监听怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring事件发布与监听怎么实现”吧!

  一、事件监听相关概念介绍

  1、流程分析

  事件:做了什么事。例如,我在写博客,写博客就是一个事件。

  监听器:监听发生事件的组件。例如,我们日常生活中的火灾报警器,监听有没有发生火灾事件。

  在一个完整的事件体系中,除了事件和监听器以外,还应该有3个概念;

  1. 事件源:事件的产生者,任何一个event都必须有一个事件源;

  2. 事件广播器:它是事件和事件监听器之间的桥梁,负责把事件通知给事件监听器;

  3. 事件监听器注册表:就是spring框架为所有的监听器提供了一个存放的地方;

  通过流程图,可以看出它们是如何各司其职的,如下:

Spring事件发布与监听怎么实现

  其实通过流程图,我们很容易发现事件体系就是观察者模式的具体实现,它并没有任何的神秘之处。

  2、流程分析

  结构分析:

  1. 事件类(ApplicaitonEvent):目前spring框架本身仅仅提供了几个事件,很多的事件都是需要自定义的。

  ApplicationEvent唯一的构造函数是ApplicaitonEvent(Object source),通过source指定事件源。 它有两个子类;

  (1)ApplicationContextEvent:容器事件,也就是说事件源是ApplicationContext,框架提供了四个子类,分别代表容器启动,刷新,停止和关闭事件。

  (2)RequestHandleEvent:这是一个与Web应用相关的事件,当一个请求被处理后,才会产生该事件。

  一般来说,我们都是扩展ApplicationEvent来自定义事件。下面会有栗子。

Spring事件发布与监听怎么实现

  2. 事件监听器接口(ApplicationListener)

  所有的监听器都需要实现该接口,该接口只定义了一个方法:onApplicaitonEvent (E event),该方法接收事件对象,在该方法中编写事件的响应处理逻辑。

Spring事件发布与监听怎么实现

  二、手写模拟事件发布与监听

  注:想直接了解Spring事件监听与发布的,可以跳过这节,但是我建议你还是看一下。

  需求:

  假设现在公司让你开发一个文件操作帮助类 ,

  定义一个文件读写方法 读写某个文件 写到某个类里面去 //但是 有时候可能会需要记录文件读取进度条的需求

  有时候需要进度条 如何实现?

  答案:我们可以采用事件发布与监听。

  事件:文件上传

  事件源:事件在哪里发布的,比如说我们在A类中,发布了事件。那么A类的对象就是事件源。

  监听器:我们编写的FileUploadListener对这个事件进行了监听。并在监听到了当前事件之后,发布事件。

  代码编写:

  

  public class ApplicationEvent {

  }

  

  public interface ApplicationListener {

  void onEvent(E e);

  }

  

  //事件管理器

  public class ListenerManage {

  //保存所有的监听器

  static List> list = new ArrayList<>();

  //添加监听器 注:如果要做的更加优雅,应该做成扫描全局,通过扫描将所有的监听器放入管理器的容器列表,这里为了方便演示就不做复杂了。

  //springboot是从spring的BeanFactory中获取listener

  public static void addListener(ApplicationListener listener) {

  list.add(listener);

  }

  //判断一下 有哪些监听器 监听了这个事件

  public static void publishEvent(ApplicationEvent event) {

  for (ApplicationListener applicationListener : list) {

  //获取ApplicationListener的泛型

  Class typeParameter = (Class) ((ParameterizedType) applicationListener.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0];

  if (typeParameter.equals(event.getClass())) {

  applicationListener.onEvent(event);

  }

  }

  }

  }

  

  public class FileUploadEvent extends ApplicationEvent {

  private int fileSize;

  private int readSize;

  public FileUploadEvent(int fileSize, int readSize) {

  this.fileSize = fileSize;

  this.readSize = readSize;

  }

  public int getFileSize() {

  return fileSize;

  }

  public void setFileSize(int fileSize) {

  this.fileSize = fileSize;

  }

  public int getReadSize() {

  return readSize;

  }

  public void setReadSize(int readSize) {

  this.readSize = readSize;

  }

  }

  

  public class FileUploadListener implements ApplicationListener {

  @Override

  public void onEvent(FileUploadEvent fileUploadEvent) {

  double molecule = fileUploadEvent.getFileSize();

  double denominator = fileUploadEvent.getReadSize();

  System.out.println("当前文件上传进度百分比:" + (denominator / molecule * 100 + "%"));

  }

  }

  

  public class FileUtil {

  public static int READ_SIZE = 100;

  public static void fileWrite(InputStream is, OutputStream os) throws Exception {

  fileWrite(is, os, null);

  }

  public static void fileWrite(InputStream is, OutputStream os, FileListener fileListener) throws Exception {

  BufferedInputStream bis = new BufferedInputStream(is);

  BufferedOutputStream bos = new BufferedOutputStream(os);

  

  //文件总大小

  int fileSize = is.available();

  //一共读取了多少

  int readSize = 0;

  byte[] readedBytes = new byte[READ_SIZE];

  //控制是否退出

  boolean exit = true;

  while (exit) {

  //文件小于第一次读的大小的时候

  if (fileSize < READ_SIZE) {

  byte[] fileBytes = new byte[fileSize];

  //将缓冲区中的数据写入到字节数组fileBytes中

  bis.read(fileBytes);

  //向文件写入fileBytes数组的内容

  bos.write(fileBytes);

  readSize = fileSize;

  exit = false;

  //当你是最后一次读的时候

  } else if (fileSize < readSize + READ_SIZE) {

  byte[] bytes = new byte[fileSize - readSize];

  readSize = fileSize;

  bis.read(bytes);

  bos.write(bytes);

  exit = false;

  } else {

  bis.read(readedBytes);

  readSize += READ_SIZE;

  bos.write(readedBytes);

  }

  //发布事件

  ListenerManage.publishEvent(new FileUploadEvent(fileSize, readSize));

  if (fileListener != null) {

  fileListener.updateLoad(fileSize, readSize);

  }

  }

  bis.close();

  bos.close();

  }

  }

  

  public class FileReadTest {

  public static void main(String[] args) throws Exception {

  ListenerManage.addListener(new FileUploadListener());

  //这里根据实际情况去设置读写的文件

  File file = new File("F:\\测试写出.txt");

  if (!file.exists()) {

  file.createNewFile();

  }

  //如果需要做进度条功能,再添加一个fileListener参数

  fileWrite(new FileInputStream(new File("F:\\明天要做的事.txt")), new FileOutputStream(file));

  }

  }

  运行结果:

  当前文件上传进度百分比:14.245014245014245%

  当前文件上传进度百分比:28.49002849002849%

  当前文件上传进度百分比:42.73504273504273%

  当前文件上传进度百分比:56.98005698005698%

  当前文件上传进度百分比:71.22507122507122%

  当前文件上传进度百分比:85.47008547008546%

  当前文件上传进度百分比:99.71509971509973%

  当前文件上传进度百分比:100.0%

  三、Spring的时间发布与监听

  我们在上面手动模拟了Spring的时间发布与监听后,看如果上面的例子后,我们使用Spring再写一个事件发布与监听的例子。郑州人流医院 http://rl.zyfuke.com/

  package com.evan.spring.config;

  import org.springframework.context.annotation.ComponentScan;

  

  @ComponentScan("com")

  public class AppConfig {

  }

  package com.evan.spring.event;

  import org.springframework.context.ApplicationContext;

  import org.springframework.context.event.ApplicationContextEvent;

  import org.springframework.context.event.ContextStartedEvent;

  

  public class WriteBlogEvent extends ApplicationContextEvent {

  String name;

  String address;

  public WriteBlogEvent(ApplicationContext source, String name, String address) {

  super(source);

  this.name = name;

  this.address = address;

  }

  public String getName() {

  return name;

  }

  public String getAddress() {

  return address;

  }

  }

  Spring的事件监听可以基于注解或实现接口。对于同一个事件,如果两个都存在,相当于多个监听器监听一个事件。

  两个监听器内的方法都会执行。

  package com.evan.spring.listener;

  import com.evan.spring.event.WriteBlogEvent;

  import org.springframework.context.ApplicationListener;

  import org.springframework.stereotype.Component;

  

  @Component

  public class WriteBlogListener implements ApplicationListener {

  @Override

  public void onApplicationEvent(WriteBlogEvent writeBlogEvent) {

  String name = writeBlogEvent.getName();

  String address = writeBlogEvent.getAddress();

  System.out.println("基于实现接口:" + name + "在" + address + "写了一篇博客");

  }

  }

  package com.evan.spring.listener;

  import com.evan.spring.event.WriteBlogEvent;

  import org.springframework.context.event.EventListener;

  import org.springframework.stereotype.Component;

  

  @Component

  public class WriteBlogListenerAnnotation {

  @EventListener

  public void annotationListen(WriteBlogEvent writeBlogEvent) {

  String name = writeBlogEvent.getName();

  String address = writeBlogEvent.getAddress();

  System.out.println("基于注解:" + name + "在" + address + "写了一篇博客");

  }

  }

  package com.evan.spring.test;

  import com.evan.spring.config.AppConfig;

  import com.evan.spring.event.WriteBlogEvent;

  import org.springframework.context.annotation.AnnotationConfigApplicationContext;

  

  public class EventTest {

  public static void main(String[] args) {

  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

  WriteBlogEvent writeBlogEvent = new WriteBlogEvent(ac, "Evan", "家里");

  ac.publishEvent(writeBlogEvent);

  }

  }

  运行结果:

  基于注解:Evan在家里写了一篇博客

  基于实现接口:Evan在家里写了一篇博客

  四、总结

  1、spring 如何得知有哪些监听器?

  通过2个步骤:1.从Bean工厂拿到所有ApplicationListener类型的Bean.

  2.扫描所有带@EventListener

  2、spring如何发布事件?

  大逻辑上通过2个步骤: 1.判断是否有监听器对该事件感兴趣

  2.调用监听器方法

感谢各位的阅读,以上就是“Spring事件发布与监听怎么实现”的内容了,经过本文的学习后,相信大家对Spring事件发布与监听怎么实现这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Spring事件发布与监听怎么实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Spring事件发布与监听怎么实现

这篇文章主要讲解了“Spring事件发布与监听怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring事件发布与监听怎么实现”吧!  一、事件监听相关概念介绍  1、流程分析  事
2023-06-02

如何实现Spring事件发布监听、顺序监听和异步监听

这篇文章给大家分享的是有关如何实现Spring事件发布监听、顺序监听和异步监听的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1. Spring的事件通知Spring的事件通知本质上就是发布-订阅,即生产者-消费者
2023-06-22

Spring的事件发布与监听方式是什么

本篇内容介绍了“Spring的事件发布与监听方式是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!事件主要代码在org.springfra
2023-07-05

详解SpringBoot实现ApplicationEvent事件的监听与发布

这篇文章主要为大家详细介绍了SpringBoot如何实现ApplicationEvent事件的监听与发布,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
2023-03-08

SpringBoot如何实现ApplicationEvent事件的监听与发布

这篇文章主要介绍“SpringBoot如何实现ApplicationEvent事件的监听与发布”,在日常操作中,相信很多人在SpringBoot如何实现ApplicationEvent事件的监听与发布问题上存在疑惑,小编查阅了各式资料,整理
2023-07-05

Spring事件发布与监听机制的用法示例

小编给大家分享一下Spring事件发布与监听机制的用法示例,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、ApplicationContext 事件机制Appl
2023-06-20

使用Spring怎么监听事件

使用Spring怎么监听事件?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、观察者模式先来看下观察者模式,举个例子警察和军人是观察者,犯罪嫌疑人是被观察者代码实现:定义被观察
2023-06-15

JavaWebListener实现事件监听与处理

JavaWeb开发中的Listener是一种事件机制,通过监听Web应用程序的事件,实现对事件的处理,从而实现更加灵活和高效的应用程序开发。Listener能够监听的事件包括应用程序启动和关闭、Session创建和销毁、请求和响应对象的创建和销毁等
2023-05-18

Android开发之Button事件实现与监听方法总结

本文实例总结了Android开发之Button事件实现与监听方法。分享给大家供大家参考,具体如下: 先来介绍Button事件实现的两种方法 main.xml
2022-06-06

Android开发怎么实现Chip监听及ChipGroup监听

这篇文章主要介绍“Android开发怎么实现Chip监听及ChipGroup监听”,在日常操作中,相信很多人在Android开发怎么实现Chip监听及ChipGroup监听问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对
2023-07-02

Vue组件事件触发和监听实现源码解析

这篇文章主要为大家介绍了Vue组件事件触发和监听实现源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-22

JavaScript怎么利用发布订阅模式编写事件监听函数

这篇“JavaScript怎么利用发布订阅模式编写事件监听函数”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“JavaScri
2023-07-06

springboot应用服务启动事件的监听怎么实现

本篇内容主要讲解“springboot应用服务启动事件的监听怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“springboot应用服务启动事件的监听怎么实现”吧!一、简介Spring B
2023-06-29

Android中的监听触摸事件怎么在Fragment中实现

本篇文章为大家展示了Android中的监听触摸事件怎么在Fragment中实现,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。activity的触摸事件 @Override public boolea
2023-05-31

Vue怎么通过监听滚动事件实现动态锚点

本文小编为大家详细介绍“Vue怎么通过监听滚动事件实现动态锚点”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue怎么通过监听滚动事件实现动态锚点”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。具体效果如下:一、
2023-07-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录