Spring事件监听机制

Spring的事件监听机制 前一节,我们了解了Spring 提供的Aware接口,我们可以通过这个实现这个接口的一些类获取到我们需要的东西。具体内容见前一节。Spring 也提供了一种单机的事件机制。可以通过发送、监听,来实现一些异步操作。使用这种类似 MQ的事件机制,我们可以通过 这个事件机制来完成一些自己的业务操作。在我们使用spring提供的事件机制时,我们只需要关注自己的事件,和自己的事件处理器。所有的事件都会继承,然后再完成对于自己时间的监听器,监听器都 实现接口,实现方法,来处理监听到的事件。 阅读详情

前言

事件监听机制其原理就是观察者模式,而观察者模式又被称为发布-订阅模式。

观察者模式将有依赖关系的对象抽象为了观察者和主题两个不同的角色,多个观察者同时观察一个主题,两者只通过抽象接口保持松耦合状态,这样双方可以相对独立的进行扩展和变化:比如可以很方便的增删观察者,修改观察者中的更新逻辑而不用修改主题中的代码。但是这种解耦进行的并不彻底,这具体体现在以下几个方面:
• ① 抽象主题需要依赖抽象观察者,而这种依赖关系完全可以去除。
• ② 主题需要维护观察者列表,并对外提供动态增删观察者的接口。
• ③ 主题状态改变时需要由自己去通知观察者进行更新。

耦合这个词在平常的开发工作中应该不陌生,简单理解就是代码中各部分关联度过高。举一个大家都遇见过的经典耦合场景:用户注册成功之后需要进行发送短信通知或是邮件通知,用户注册逻辑与发送短信或是邮件通知逻辑放在一块就是一种耦合现象,如果短信或是邮件功能异常,整个用户注册功能就会异常,会带来不好的用户体验,另外的缺点是维护复杂,不便于拓展。将业务逻辑与功能性逻辑进行拆分开就是属于解耦。spring中IOC思想就是解耦的一种体现,毕竟在一个实现类中如果调用另一个实现类不用繁琐的创建对象,只需要把需要用到实现类进行注入就可以了,减少代码量的同时也便于后期的拓展与维护。

可以把主题(Subject)替换成事件(event),把对特定主题进行观察的观察者(Observer)替换成对特定事件进行监听的监听器(EventListener),而把原有主题中负责维护主题与观察者映射关系以及在自身状态改变时通知观察者的职责从中抽出,放入一个新的角色事件发布器(EventPublisher)中,事件监听模式的轮廓就展现在了我们眼前,如下图所示:
在这里插入图片描述
常见事件监听机制的主要角色如下:
• 事件及事件源:对应于观察者模式中的主题。事件源发生某事件是特定事件监听器被触发的原因。
• 事件监听器:对应于观察者模式中的观察者。监听器监听特定事件,并在内部定义了事件发生后的响应逻辑。
• 事件发布器:事件监听器的容器,对外提供发布事件和增删事件监听器的接口,维护事件和事件监听器

事件监听机制的应用场景

在程序设计里有哪些场景会用到呢?下面举一些例子: 用户注册或者登陆,或者用户下单成功都需要发个短信或者邮件提示用户,简单抽象一下,用户的很多业务行为都会有要发短信的需求,如果每个业务行为都各自发短信,那么首先业务行为与发短信就耦合了,不利于后续扩展,其次具有相同特征的行为一直重复。使用事件监听机制改造一下,把各个业务行为内的短信内容封装成一个事件,业务行为触发的时候发布这个事件,再把具体发短信的行为封装到监听器里,监听到事件源发布的事件后,触发具体的发短信的行为。

事件监听机制的好处

业务与业务之间解耦,符合依赖倒置原则;
代码复用,更容易维护,也提高了执行效率;

Spring容器对事件监听机制的支持

Spring容器,具体而言是ApplicationContext接口定义的容器提供了一套相对完善的事件发布和监听框架,其遵循了JDK中的事件监听标准,并使用容器来管理相关组件,使得用户不用关心事件发布和监听的具体细节,降低了开发难度也简化了开发流程。下面看看对于事件监听机制中的各主要角色,Spring框架中是如何定义的,以及相关的类体系结构。

事件

Spring为容器内事件定义了一个抽象类ApplicationEvent,该类继承了JDK中的事件基类EventObject。因而自定义容器内事件除了需要继承ApplicationEvent之外,还要传入事件源作为构造参数。

在这里插入图片描述

事件监听器

Spring定义了一个ApplicationListener接口作为事件监听器的抽象,接口定义如下:

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

(1)该接口继承了JDK中表示事件监听器的标记接口EventListener,内部只定义了一个抽象方法onApplicationEvent(evnt),当监听的事件在容器中被发布,该方法将被调用。
(2)同时,该接口是一个泛型接口,其实现类可以通过传入泛型参数指定该事件监听器要对哪些事件进行监听。这样有什么好处?这样所有的事件监听器就可以由一个事件发布器进行管理,并对所有事件进行统一发布,而具体的事件和事件监听器之间的映射关系,则可以通过反射读取泛型参数类型的方式进行匹配,稍后我们会对原理进行讲解。
(3)最后,所有的事件监听器都必须向容器注册,容器能够对其进行识别并委托容器内真正的事件发布器进行管理。

事件发布器

ApplicationContext接口继承了ApplicationEventPublisher接口,从而提供了对外发布事件的能力,如下所示:
在这里插入图片描述
那么是否可以说ApplicationContext,即容器本身就担当了事件发布器的角色呢?其实这是不准确的,容器本身仅仅是对外提供了事件发布的接口,真正的工作其实是委托给了具体容器内部一个ApplicationEventMulticaster对象,其定义在AbstractApplicationContext抽象类内部,如下所示:
在这里插入图片描述
在这里插入图片描述

所以,真正的事件发布器是ApplicationEventMulticaster,这是一个接口,定义了事件发布器需要具备的基本功能:管理事件监听器以及发布事件。
在这里插入图片描述
其默认实现类是
SimpleApplicationEventMulticaster,该组件会在容器启动时被自动创建,并以单例的形式存在,管理了所有的事件监听器,并提供针对所有容器内事件的发布功能。

在这里插入图片描述

AbstractApplicationContext#refresh方法中的initApplicationEventMulticaster()步骤会判断是否存在,不存在就实例化一个SimpleApplicationEventMulticaster。

具体实现细节看
Spring事件监听源码解析

基于Spring实现对任务执行结果的监听

基于Spring框架来实现对自定义事件的监听需要三步:
• ① 继承spring事件基类ApplicationEvent,完成事件的封装;
• ② 实现ApplicationListener接口或者通过@EventListener注解,把事件监听器注册到spring容器里;
• ③ 业务类要实现ApplicationEventPublisherAware接口或者引用ApplicationContext,把spring的事件发布器注入到业务类里,在触发事件的时候,spring的事件发布器发布事件;

自定任务结束事件

定义一个任务结束事件SignInEvent,该类继承抽象类ApplicationEvent来遵循容器事件规范。

public class SignInEvent extends ApplicationEvent {
    private static final long serialVersionUID = -578995207794413821L;

    /**
     * Create a new {@code ApplicationEvent}.
     *
     * @param source the object on which the event initially occurred or with
     *               which the event is associated (never {@code null})
     */
    public SignInEvent(Object source) {
        super(source);
    }
}

自定义短信服务监听器并向容器注册

该类实现了容器事件规范定义的监听器接口,通过泛型参数指定对上面定义的任务结束事件进行监听,通过@Component注解向容器进行注册。

@Slf4j
@Component
public class MesTaskListener1 implements ApplicationListener<SignInEvent> {
    @Override
    public void onApplicationEvent(SignInEvent event) {
        User user = (User) event.getSource();

        // 调用具体的发送短信接口
        log.info("send message to user : {}", JSON.toJSONString(user));
    }
}

也可以通过注解的方式实现

@Slf4j
@Component
public class MesTaskListener2 {

    @EventListener
    public void doSendMesEvent(SignInEvent event) {
        User user = (User) event.getSource();

        // 调用具体的发送短信接口
        log.info("send message to user : {}", JSON.toJSONString(user));
    }
}

发布事件

从上面对Spring事件监听机制的类结构分析可知,发布事件的功能定义在ApplicationEventPublisher接口中,而ApplicationContext继承了该接口,所以最好的方法是通过实现ApplicationContextAware接口获取ApplicationContext实例,然后调用其发布事件方法。如下所示定义了一个发布容器事件的代理类:

@Component
public class SignInServiceImpl implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    public Boolean signIn(User user) {
        // 登录成功
        // 发布事件
        publishEvent(new SignInEvent(user));

        return Boolean.TRUE;
    }

    // 发布事件
    public void publishEvent(ApplicationEvent event) {
        applicationContext.publishEvent(event);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

因为ApplicationContext继承了ApplicationEventPublisher接口,也可以直接通过ApplicationContext调用其发布事件方法。

@Component
public class SignInServiceImpl2 {
    @Autowired
    private ApplicationContext applicationContext;

    public Boolean signIn(User user) {
        // 登录成功
        // 发布事件
        applicationContext.publishEvent(new SignInEvent(user));

        return Boolean.TRUE;
    }
}

在此基础上,还可以自定义一个邮件服务监听器,在任务执行结束时发送邮件通知用户。过程和上面自定义短信服务监听器类似:实现ApplicationListner接口并重写抽象方法,然后通过注解或者xml的方式向容器注册。

@Slf4j
@Component
public class EmailTaskListener {

    @EventListener
    public void doSendEmailEvent(SignInEvent event) {
        User user = (User) event.getSource();

        // 调用具体的发送短信接口
        log.info("send Email to user : {}", JSON.toJSONString(user));
    }
}

测试发布事件

@RunWith(SpringRunner.class)
@SpringBootTest()
public class SpringTest {
    @Autowired
    private SignInServiceImpl1 signInService;

    @Test
    public void testEvent() {
        signInService.signIn(User.builder().id(123546L).name("小明").phone("15232654678").build());
    }
}

测试结果

在这里插入图片描述

看到这里是不是有个疑问?

1.如果想要改变自定义监听器的执行顺序该怎么做?
2.如果其中某个自定义事件发生异常,会不会影响其它自定义事件?

我们来看下:
1.执行顺序
注解方式:
使用注解 @Order() 和 @EventListener :
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意:Order的值越小,优先级越高

2.异常问题
我们自己写一个异常

在这里插入图片描述
在这里插入图片描述

可以看到一个事件发生异常后,剩余的事件都不能执行,这个时候我们可以使用@Async 注解来解决

在这里插入图片描述
在这里插入图片描述
启动后发现:
在这里插入图片描述
task-scheduler-1发送短信的异常并不影响task-scheduler-2发送邮箱业务

Spring事件监听机制使用和原理解析 如下定义了一个事件AppEvent,它继承了ApplicationEvent类,如果我们要使用Spring的事件监听机制,那么我们定义的事件必须继承ApplicationEvent ,否则就无法使用。java复制代码/*** 功能说明: 事件* * Original @Author: steakliu-刘牌, 2023-03-30 11:02* */ 阅读详情

相关推荐

SpringBoot 事件发布监听机制使用、分析、注意点 (一篇到位)

事件发布监听机制使用、分析、注意点

默默不代表沉默 1万+

Spring 中的事件监听机制

ApplicationContext 中的事件处理是通过ApplicationEvent 类和ApplicationListener 接口实现的。如果一个 Bean(监听器实例)实现了ApplicationListener 接口,并被部署到 Spring 容器中,那么每次在容器中发布一个ApplicationEvent 事件,该 Bean (监听器实例)都会被通知到。本质上,这种机制就是一个观察者的设计模式。

swadian2008的博客 5762

Mac上Office合法安装与激活全指南:2021/2024/M365区别解析

Office是微软办公套件的核心产品,其在macOS平台的部署逻辑与Windows截然不同——不依赖传统密钥激活,而是基于Microsoft账户与设备标识的云端绑定机制。理解这一原理,是解决‘无法验证开发者’‘打不开’‘功能受限’等常见问题的前提。Office 2021代表永久许可模型,Office 2024 LTSC面向企业离线场景,Microsoft 365则是持续订阅服务,三者在授权验证方式、更新策略与系统兼容性上存在本质差异。实际应用中,需结合macOS版本、芯片架构(Intel/Apple Sil

weixin_33491377的博客 1174

Spring的监听机制详解

假设我们正在开发一个在线商城应用程序,我们需要在用户下单时发送一个通知邮件给商家。为了实现这个功能,我们可以使用自定义事件来触发邮件发送操作。首先,我们需要定义一个名为OrderPlacedEvent的自定义事件,用于表示用户下单的事件。import org} }} }在上述代码中,我们定义了一个名为OrderPlacedEvent的自定义事件,并通过实现构造函数和getOrder()方法来传递订单参数和获取订单参数。

yinying293的博客 2115

【深圳】IBM V3500存储维修 更换控制器故障

今天给大家分享的是深圳.福田区一个电商客户公司一台IBM Storwize v3500存储控制器故障从远程诊断 收集日志 分析结果的实际案例,如图所示通过存储管理口登陆进去后直接看到少了一个控制器,经过工程师分析日志后判定为该控制器损坏,接下来更换控制器配件,标准套件的控制器不带子卡和电池,所以需要把故障控制器上的子卡和电池拆下来装到新控制器上,这个电池拆还需要点技巧,接着把新的控制器插回V3500主机,等待大约十分钟后,新控制器指示灯全绿,管理界面看到节点已联机;冠峰科技-爱科技爱分享。

OuYangYuXi的博客 4574

Python+OpenCV实战:5分钟搞定机械臂手眼标定(眼在手上模式)

本文详细介绍了使用Python和OpenCV在5分钟内完成机械臂手眼标定(眼在手上模式)的实战教程。通过解析相机坐标系与机械臂基坐标系的转换关系,提供从数据采集到标定矩阵计算的全流程代码实现,帮助开发者快速解决AX=XB问题,提升机械臂视觉引导精度。

weixin_33670786的博客 495

事件监听机制(四)从Java事件监听到Spring事件监听

从Java事件监听到Spring事件监听 java 事件监听 1. 发布订阅模式 java.util.Observable发布者 public class Observable { private boolean changed = false; private Vector&lt;Observer&gt; obs; /** Construct an Observable...

java界的小学生 1535

电机控制必看!SVPWM谐波优化:5段式与7段式全参数对比测试

本文通过实测数据,对比分析了电机控制中5段式与7段式SVPWM控制算法的谐波性能。实验表明,7段式SVPWM在电流波形质量(THD)和低速性能上更优,而5段式SVPWM则在开关损耗和效率方面表现突出。文章为工程师在不同应用场景(如对噪音、效率或动态响应的侧重)下的算法选型提供了清晰的依据和实用的工程指南。

weixin_28331555的博客 177

spring中的事件监听机制

Spring event listener介绍自定义事件、监听和发布事件: 介绍 spring支持自定义的事件发布。 spring的事件机制基于ApplicationListener这个接口。 /* Interface to be implemented by application event listeners.Based on the standard {@code java.util.EventListener} interface for the Observer design pattern.

weixin_43810802的博客 1500

告别Keil手动分区!用CubeMX+VS Code一键生成带Bootloader的STM32 OTA工程

本文详细介绍了如何利用STM32CubeMX和VS Code实现STM32 OTA工程的自动化构建,告别传统Keil手动分区的繁琐流程。通过图形化配置Flash分区、自动生成链接脚本以及实现Bootloader跳转逻辑,开发者可以高效完成远程升级功能开发,显著提升嵌入式开发效率。

weixin_33720956的博客 389

Jetson Nano系统重装的艺术:从格式化到烧录的深度解析

本文详细解析了Jetson Nano系统重装的完整流程,从SD卡格式化到系统镜像烧录的进阶技巧,包括硬件选择、软件准备、常见问题处理及深度学习环境配置。特别推荐使用三星EVO Plus SD卡和官方电源以确保稳定性,适合开发者快速掌握嵌入式设备系统重装的核心技术。

weixin_28273593的博客 610

Spring事件监听机制详解

Spring事件监听机制是一种基于观察者模式的设计,通过发布和监听事件,使得不同组件可以解耦地进行交互。事件类 (:封装需要传递的信息。事件发布者 (:负责发布事件。事件监听器 (:监听并处理事件。Spring事件监听机制通过和实现了组件之间的松耦合,增强了系统的灵活性和可扩展性。通过发布和监听事件,可以实现更高效、更模块化的应用设计。这一机制广泛应用于各种场景,如用户注册、订单处理、日志记录等。希望通过本文的介绍,大家能够更好地理解和应用Spring事件监听机制,为项目设计带来更多的便利和灵活性。

Evan 928

系统建模语言 (SysML)

系统建模语言

追赶时代的博客 749

事件监听机制(二)Spring事件监听

事件监听机制(二)Spring事件监听 事件监听实现流程 事件对象: 继承自java.util.EventObject对象,由开发者自行定义实现。 事件源: 就是触发事件的源头,不同的事件源会触发不同的事件类型。 事件监听器: 事件监听器负责监听事件源发出的事件,事件监听器可以通过实现java.util.EventListener这个标识接口.,实现事件监听。 流程总结 事件源可以...

java界的小学生 1916

AI智能体丨使用Coze生成自媒体短视频分镜生成器(附保姆级教程)

【短视频分镜脚本生成器】是一款由Coze平台开发出来的智能体,可快速解析某音/某书视频或本地文件,自动生成专业分镜脚本。用户只需输入视频链接或上传文件,系统即会分析镜头节奏、叙事逻辑和画面内容,输出包含画面、模板和话术参考的标准化脚本(支持3分钟内视频)。该工具还能生成HTML网页和可下载图片,提供可视化呈现。工作流程包括视频解析、帧提取、AI画面理解、脚本生成和网页制作,大幅提升短视频创作效率。

李同学Lino的博客 1533

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Spring 事件监听机制及原理分析

简介 在JAVA体系中,有支持实现事件监听机制,在Spring 中也专门提供了一套事件机制的接口,方便我们实现。比如我们可以实现当用户注册后,给他发送一封邮件告诉他注册成功的一些信息,比如用户订阅的主题更新了,通知用户注意及时查看等。 观察者模式 观察者模式还有很多其他的称谓,如发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对

gumenghua_com1的博客 687

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

深入理解Spring事件监听机制

​ 对于开发者来说,使用 Spring 监听机制非常简单。只需要实现事件和监听器接口,并在代码中注册监听器即可。Spring 会自动管理事件和监听器的生命周期,确保它们的正确运行。同时,由于 Spring 监听器使用了异步执行机制,因此不会影响主线程的运行效率,保证了应用程序的高并发和高效性。

大张伟 1033

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Spring事件监听机制及其原理

Sprin事件监听机制是Spring框架中的一项重要技术,它允许在组件之间进行松耦合的通信,通过使用事件监听机制,应用程序的各个组件可以在不直接引用其它组件的情况下,相关通信。通过对Spring事件原理的解析来理解Spring事件监听机制

m0_37636269的博客 1471

Spring 事件监听机制详解

Spring事件监听机制是观察者模式的一种实现,它允许我们在应用中实现松耦合的组件间通信。通过事件监听,我们可以在某些操作发生时自动触发其他相关的业务逻辑,而无需直接调用。

m0_74399067的博客 628

技术派Spring事件监听机制及原理

这篇内容通过源码的形式讲解了 Spring 事件监听机制及其原理。

qq_64948664的博客 1437
上一篇: MyBatis常用知识点总结
下一篇: Spring事件监听源码解析
CodAlun
博客等级 码龄8年 46粉丝 96原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值