此文转载,请查看原文:

https://baijiahao.baidu.com/s?id=1617119527751442850&wfr=spider&for=pc

前言

今天去官网查看spring boot资料时,在特性中看见了系统的事件及监听章节。想想,spring的事件应该是在3.x版本就发布的功能了,并越来越完善,其为bean和bean之间的消息通信提供了支持。比如,我们可以在用户注册成功后,发送一份注册成功的邮件至用户邮箱或者发送短信。使用事件其实最大作用,应该还是为了业务解耦,毕竟用户注册成功后,注册服务的事情就做完了,只需要发布一个用户注册成功的事件,让其他监听了此事件的业务系统去做剩下的事件就好了。对于事件发布者而言,不需要关心谁监听了该事件,以此来解耦业务。今天,我们就来讲讲spring boot中事件的使用和发布。当然了,也可以使用像guava的eventbus或者异步框架Reactor来处理此类业务需求的。本文仅仅谈论ApplicationEvent以及Listener的使用。

一点知识

示例前,我们来了解下相关知识点。

Java的事件机制

java中的事件机制一般包括3个部分:EventObject,EventListener和Source。

EventObject

java.util.EventObject是事件状态对象的基类,它封装了事件源对象以及和事件相关的信息。所有java的事件类都需要继承该类。

EventListener

java.util.EventListener是一个标记接口,就是说该接口内是没有任何方法的。所有事件监听器都需要实现该接口。事件监听器注册在事件源上,当事件源的属性或状态改变的时候,调用相应监听器内的回调方法。

Source

事件源不需要实现或继承任何接口或类,它是事件最初发生的地方。因为事件源需要注册事件监听器,所以事件源内需要有相应的盛放事件监听器的容器。

java的事件机制是一个观察者模式。大家可以根据这个模式,自己实现一个。可以看看这篇博文:《java事件机制》一个很简单的实例。

Spring的事件

ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性。

ApplicationEvent就是Spring的事件接口ApplicationListener就是Spring的事件监听器接口,所有的监听器都实现该接口ApplicationEventPublisher是Spring的事件发布接口,ApplicationContext实现了该接口ApplicationEventMulticaster就是Spring事件机制中的事件广播器,默认实现SimpleApplicationEventMulticaster在Spring中通常是ApplicationContext本身担任监听器注册表的角色,在其子类AbstractApplicationContext中就聚合了事件广播器ApplicationEventMulticaster和事件监听器ApplicationListnener,并且提供注册监听器的addApplicationListnener方法。

其执行的流程大致为:

当一个事件源产生事件时,它通过事件发布器ApplicationEventPublisher发布事件,然后事件广播器ApplicationEventMulticaster会去事件注册表ApplicationContext中找到事件监听器ApplicationListnener,并且逐个执行监听器的onApplicationEvent方法,从而完成事件监听器的逻辑。

在Spring中,使用注册监听接口,除了继承ApplicationListener接口外,还可以使用注解@EventListener来监听一个事件,同时该注解还支持SpEL表达式,来触发监听的条件,比如只接受编码为001的事件,从而实现一些个性化操作。下文示例中会简单举例下。

简单来说,在Java中,通过java.util. EventObject来描述事件,通过java.util. EventListener来描述事件监听器,在众多的框架和组件中,建立一套事件机制通常是基于这两个接口来进行扩展。

SpringBoot的默认启动事件

在SpringBoot1.5.x中,提供了几种事件,供我们在开发过程中进行更加便捷的扩展及差异化操作。

ApplicationStartingEvent:springboot启动开始的时候执行的事件ApplicationEnvironmentPreparedEvent:spring boot对应Enviroment已经准备完毕,但此时上下文context还没有创建。在该监听中获取到ConfigurableEnvironment后可以对配置信息做操作,例如:修改默认的配置信息,增加额外的配置信息等等。ApplicationPreparedEvent:spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。在获取完上下文后,可以将上下文传递出去做一些额外的操作。值得注意的是:在该监听器中是无法获取自定义bean并进行操作的。ApplicationReadyEvent:springboot加载完成时候执行的事件。ApplicationFailedEvent:spring boot启动异常时执行事件。

从官网文档中,我们可以知道,由于一些事件实在上下文为加载完触发的,所以无法使用注册bean的方式来声明,文档中可以看出,可以通过SpringApplication.addListeners(…)或者SpringApplicationBuilder.listeners(…)来添加,或者添加META-INF/spring.factories文件z中添加监听类也是可以的,这样会自动加载。

启动类中添加:

所以在需要的时候,可以通过适当的监听以上事件,来完成一些业务操作。

自定义事件发布和监听

通过以上的介绍,我们来定义一个自定义事件的发布和监听。

0.加入POM依赖,这里为了演示加入了web依赖。事件相关类都在spring-context包下。

1.自定义事件源和实体。

MessageEntity.java

CustomEvent.java

2.编写监听类使用@EventListener方式。

**注意:

Spring中,事件源不强迫继承ApplicationEvent接口的,也就是可以直接发布任意一个对象类。但内部其实是使用PayloadApplicationEvent类进行包装了一层。这点和guava的eventBus类似。**而且,使用@EventListener的condition可以实现更加精细的事件监听,condition支持SpEL表达式,可根据事件源的参数来判断是否监听。

使用ApplicationListener方式。

3.编写控制类,示例发布事件。

4.编写启动类。

这里,创建了个ApplicationStartingEvent事件监听类。

5.启动应用,控制台可以看出,在启动时,我们监听到了ApplicationStartingEvent事件

首先访问下:http://127.0.0.1:8080/push?code=lqdev&message=趔趄的猿,可以看见事件已经被监听到了,而监听了code为oKong的监听未触发。

然后访问下:http://127.0.0.1:8080/push?code=oKong&message=趔趄的猿,可以看见此时三个监听事件都接收到了事件了。

此时,由于写了一个监听所有事件的方法,可以看见请求结束后,会发布一个事件,ServletRequestHandledEvent,里面记录了请求的时间、请求url、请求方式等等信息。

异步监听处理

默认情况下,监听事件都是同步执行的。在需要异步处理时,可以在方法上加上@Async进行异步化操作。此时,可以定义一个线程池,同时开启异步功能,加入@EnableAsync。对于异步处理,可以查看之前发布的文章:《第二十一章:异步开发之异步调用》。里面有详细的介绍异步调用,这里就不阐述了。

异步简单示例:

关于事务绑定事件

当一些场景下,比如在用户注册成功后,即数据库事务提交了,之后再异步发送邮件等,不然会发生数据库插入失败,但事件却发布了,也就是邮件发送成功了的情况。此时,我们可以使用@TransactionalEventListener注解或者TransactionSynchronizationManager类来解决此类问题,也就是:事务成功提交后,再发布事件。当然也可以利用返回上层(事务提交后)再发布事件的方式了,只是不够优雅而已罢了,其实能起作用就好了,是吧~

本例中未使用到数据库,就不示例了,都在Spring-tx包下。

具体可查看文章:Spring Event 事件中的事务控制

参考资料

https://docs.spring.io/spring-boot/docs/1.5.15.RELEASE/reference/htmlsingle/#boot-features-application-events-and-listenershttps://blog.csdn.net/eos2009/article/details/77773551https://www.cnblogs.com/senlinyang/p/8496099.html总结

本章节主要简单介绍了spring的事件机制。感兴趣的同学,可以编写一个监听所有事件的方法,然后看看系统运行各类请求或者相关操作时,系统会发布哪些事件,了解后可以在之后碰见一些特殊业务需求时,可以适当的监听相关的事件来完成特定的业务公共。同时对这种观察者模式,大家还可以看看eventbus和reactor了。后者没用过,有时间倒是可以看看。最近买了本RxJava2书籍,确实要好好补课下了。

SpringBoot:事件的发布和监听相关推荐

  1. SpringBoot | 第三十二章:事件的发布和监听

    前言 今天去官网查看spring boot资料时,在特性中看见了系统的事件及监听章节.想想,spring的事件应该是在3.x版本就发布的功能了,并越来越完善,其为bean和bean之间的消息通信提供了 ...

  2. Spring事件发布与监听

    最近算是把spring整体的又过了一遍,发现很多东西虽然用的多,但是有些思想理解的不够透彻,在此记录下, 顺便感叹下,spring源码看了大部分,这才没过多久又忘了 TnT . 一.事件监听相关概念介 ...

  3. Android事件的响应,Android 开发事件响应之基于监听的事件响应

    Android 开发事件响应之基于监听的事件响应 本文将介绍Android 操作系统如何通过监听来实现对事件的响应. Android 开发事件响应之基于监听的事件响应 背景介绍 Android 开发事 ...

  4. html中下拉列表监听事件,ExtJS 下拉框监听事件、日期选择器监听事件、实现动态给items添加删除数据...

    本文将为您描述ExtJS 下拉框监听事件.日期选择器监听事件.实现动态给items添加删除数据,具体实现方法: 1.下拉框 下拉框选择时,触发事件的方法: 在 Ext.form.ComboBox 组件 ...

  5. SpringBoot ApplicationListener监听器的使用-监听ApplicationReadyEvent事件

    SpringBoot监听器 ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现Applic ...

  6. springboot13 发布和监听事件

    spring中的事件驱动模型Event(也叫发布订阅模式),是观察者模式的一个典型的应用 好处:业务解耦,在不影响原来业务逻辑的情况下,加入其它业务 场景: app上线后已实现用户注册功能,现需要在用 ...

  7. Springboot redis多数据源过期监听案例

    在上一篇Springboot redis多数据源案例中,我们实现了springboot下多数据源的案例. 本篇博客在此基础上,实现多数据源过期监听事件: 监听器配置类: package com.xin ...

  8. java怎么设置不同事件_activiti 全局流程监听ActivitiEventListener,实现监听不同类型事件,不需要在acitivit中配置任务监听,非常方便...

    如果我们像给任务配置监听,按照常规的做法是这样的 一个个配置,比较麻烦. 现在利用ActivitiEventListener,监听全局事件,并且可以判断不同的事件类型,进而执行不同的业务逻辑. 1.定 ...

  9. jquery 监听td点击事件_安卓开发监听点击事件的一种方法

    本人是菜鸟一只,学习安卓纯属兴趣.没有真正上过编程课程,所有知识都是在网上获取的.今天分享的是监听点击事件的一个方法,这个方法的好处是代码较简洁. 如图,点击保存时,把上面的数据入库. 实现如下: 在 ...

  10. 监听关闭页面事件 ajax,Vue 实现监听窗口关闭事件,并在窗口关闭前发送请求

    网上很多博客说监听窗口关闭事件使用window.beforeunload,但是这个监听事件也会在页面刷新的时候执行,经过百度和自己的实际测试, 终于解决了这个问题,代码如下: mounted() { ...

最新文章

  1. Spring Boot 项目瘦身指南,瘦到不可思议!
  2. 一年级大括号问题专项训练_一年级小学生自信满满地交了试卷,以为会考满分,结果很打脸...
  3. python爬虫文字全是乱码_pythone爬虫编码自适应 解决网页乱码
  4. POJ - 2187 Beauty Contest(最远点对)
  5. 论文浅尝 | emrKBQA: 一个面向临床医疗问答的KBQA数据集
  6. Nginx接受代理协议
  7. python3 readlines的参数_Python3 File readlines() 方法
  8. Struts2——知识点:Action Implements SessionAware
  9. 2017年2月24号课堂笔记
  10. Pandas 基础(4) - 读/写 Excel 和 CSV 文件
  11. 【原创工具】蓝牙串口无线烧写STM32程序的工具,支持HC-05和CC2541两种蓝牙模块
  12. 77个互联网+大学生创新创业大赛文档
  13. 电脑软件安装手册 2019年4月22日
  14. 电子/自动化专业常用软件介绍
  15. QQ音乐的歌曲真实地址解析
  16. [BZOJ5109/CodePlus2017]大吉大利,晚上吃鸡!
  17. windows系统使用的那点事(1)-解决win10的EN输入法不见了
  18. 黑色沙漠首发五职业PVP强度排行
  19. javascript 取整,取余数
  20. 隐私计算秘密学-秘密分享

热门文章

  1. ESET Smart Security 3.0667与WindowsXP Sp3冲突
  2. buildroot 文件系统添加telnet, ssh, 以及制作注意事项
  3. 递归解决换零钱问题--代码实现
  4. Ubuntu 12.04重启后丢失resolv.conf问题
  5. 恢复出厂设置 卡住10分钟问题
  6. 基于M6097 switch的STP协议调试方法
  7. Linux进程的管理与调度(八) -- Linux下进程的创建过程分析(_do_fork/do_fork详解)
  8. “CEPH浅析”系列之六——CEPH与OPENSTACK
  9. ffmpeg 如何音视频同步
  10. Linux内核CPU负载均衡机制