当前位置: 首页 > news >正文

Spring的监听机制详解

Spring的监听机制详解

  讲在前面

      对Spring框架,大家都已不陌生,它给我们提供了很多功能,包括IoC、AOP、事务管理等。其中,Spring的事件监听机制是一项非常重要的功能,它允许开发人员定义和处理自定义事件,并在应用程序中发布和监听这些事件。

       这个机制可以让我们更加灵活地响应应用程序中发生的事件,同时还可以减少不同组件之间的耦合度。本文老朱将介绍Spring的事件监听机制,包括如何使用Spring提供的标准事件和如何定义和处理自定义事件。同时,我们还将讨论这个机制的底层原理和常见的应用场景。

1 Spring事件监听机制的原理

      Spring 的监听机制是非常优秀的思想,它能够很好地实现代码解耦,将业务逻辑与非业务逻辑分离,让程序变得更加灵活和可维护。在业务开发中,我们可以借鉴这种思想,例如电商下单场景,下单业务的核心逻辑只与下单有关,但下单完成后,我们需要执行非业务逻辑,如发通知和记录用户行为日志,这些非业务逻辑可以通过监听器来解耦,从而实现代码的灵活和可维护性。那么监听机制的底层原理是什么呢?我们一起分析下。

      实现Spring事件机制主要有4个接口:

1.1 ApplicationEventPublisher:事件发布

javaCopy code
public interface ApplicationEventPublisher {void publishEvent(ApplicationEvent event);void publishEvent(Object event);

1.2 ApplicationListener:事件监听

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {void onApplicationEvent(E event);
}

1.3 ApplicationEvent:事件

public abstract class ApplicationEvent extends EventObject {private final long timestamp;public ApplicationEvent(Object source) {super(source);this.timestamp = System.currentTimeMillis();}public long getTimestamp() {return this.timestamp;}public String toString() {return getClass().getSimpleName() + "{timestamp=" + this.timestamp + ", source=" + getSource() + "}";}
}

1.4 ApplicationEventMulticaster:事件广播器,Spring中负责事件的发布和监听的核心接口

public interface ApplicationEventMulticaster {//用于向事件广播器注册一个监听器。在广播器发送事件时,这个监听器将会接收到事件。void addApplicationListener(ApplicationListener<?> listener);//用于将一个已经注册的监听器从事件广播器中移除。void removeApplicationListener(ApplicationListener<?> listener);//用于移除所有注册的监听器。void removeAllListeners();//用于向所有已注册的监听器广播一个事件。void multicastEvent(ApplicationEvent event);
}

      Spring的源码中,当初始化beanfacotory时,我们会发现Spring会初始化事件广播器以及注册事件监听器源码如下,标红的源码你们追进去看看,逻辑很简单。
在这里插入图片描述

2 Spring框架内部事件监听机制的应用

      在Spring框架中,有许多预定义的事件,这些事件涵盖了Spring的生命周期、Web应用程序上下文的生命周期以及许多其他方面。下面是一些常见的Spring事件:

  1. ContextRefreshedEvent:

    当ApplicationContext被初始化或刷新时触发该事件。

  2. ContextStartedEvent:

    当ApplicationContext被启动时触发该事件,即在所BeanDefinition都已加载和bean初始化之后。

  3. ContextStoppedEvent:

    当ApplicationContext被停止时触发该事件,即在所有singleton bean被销毁之前。

  4. ContextClosedEvent:

    当ApplicationContext被关闭时触发该事件,即在所有singleton bean被销毁之后。

  5. RequestHandledEvent:

    在Web应用程序上下文中,当HTTP请求被处理完毕后触发该事件。

  6. ServletRequestHandledEvent:

    与RequestHandledEvent类似,但是专为Spring的DispatcherServlet设计。

      除了这些预定义的事件之外,开发人员还可以创建自己的自定义事件,并使用ApplicationEventPublisher接口将其发布到应用程序上下文中。

3 自定义监听

      假设我们正在开发一个在线商城应用程序,我们需要在用户下单时发送一个通知邮件给商家。为了实现这个功能,我们可以使用自定义事件来触发邮件发送操作。

      首先,我们需要定义一个名为OrderPlacedEvent的自定义事件,用于表示用户下单的事件。代码如下:

package com.qf.listener;import org.springframework.context.ApplicationEvent;public class OrderPlacedEvent extends ApplicationEvent {private Order order;public OrderPlacedEvent(Object source, Order order) {super(source);this.order = order;}public Order getOrder() {return order;}
}

      在上述代码中,我们定义了一个名为OrderPlacedEvent的自定义事件,并通过实现构造函数和getOrder()方法来传递订单参数和获取订单参数。

      然后,我们需要定义一个名为OrderPlacedEventListener的自定义事件监听器,用于处理用户下单事件并触发邮件发送操作。代码如下:

package com.qf.listener;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;import org.springframework.stereotype.Component;@Component
public class OrderPlacedEventListener {@EventListenerpublic void handleOrderPlacedEvent(OrderPlacedEvent event) {Order order = event.getOrder();String message = "您有一个新的订单,订单号为:" + order.getOid();//todo 发邮件System.out.println("message = " + message);}
}

      在上述代码中,我们定义了一个名为OrderPlacedEventListener的自定义事件监听器,在handleOrderPlacedEvent()方法中,我们从事件对象中获取订单参数,然后发送邮件(具体邮件代码此处省略)最后,当用户下单成功时,我们需要在订单服务对象中触发OrderPlacedEvent事件,以便通知邮件能够被发送。代码如下:

package com.qf.listener;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;@Service
public class OrderService {@Autowiredprivate ApplicationEventPublisher eventPublisher;public void placeOrder(Order order) {// 订单保存逻辑// ...// 触发订单下单事件eventPublisher.publishEvent(new OrderPlacedEvent(this, order));}
}

      在上述代码中,我们定义了一个名为OrderService的订单服务对象,并使用@Autowired注解来注入一个事件发布器对象。在placeOrder()方法中,我们调用订单保存逻辑,然后使用事件发布器对象触发OrderPlacedEvent事件,并传递订单参数。

      通过上述代码,我们可以在用户下单时触发OrderPlacedEvent事件,并通过自定义事件监听器处理该事件并触发邮件发送操作。

4 Spring事件监听机制的优点

Spring事件监听机制具有以下优点:

1.松耦合:通过事件监听机制,组件之间的耦合度得到了很大的降低,每个组件只需要监听自己感兴趣的事件,不需要关心其他组件的实现细节。

2.可扩展性:通过定义新的事件类型和监听器,应用程序的功能可以随着需求的变化而不断扩展。

3.高可靠性:事件监听机制可以保证应用程序的可靠性,即使某个组件出现异常或错误,其他组件仍然可以正常运行。

5 总结

      Spring 监听机制是一种非常优秀的设计模式(观察者模式),它可以实现代码的解耦和模块化。通过定义事件和监听器,我们可以将代码的不同模块分离开来,以便更好地维护和修改。Spring 框架内置了许多事件和监听器,如上下文事件、Bean 事件、Web 事件等,开发者也可以根据具体需求自定义事件和监听器。

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

相关文章:

Spring的监听机制详解

Spring的监听机制详解 讲在前面 对Spring框架&#xff0c;大家都已不陌生&#xff0c;它给我们提供了很多功能&#xff0c;包括IoC、AOP、事务管理等。其中&#xff0c;Spring的事件监听机制是一项非常重要的功能&#xff0c;它允许开发人员定义和处理自定义事件&#xff0c;并…...

Cache结构

Cache cache的一般设计 超标量处理器每周期需要从Cache中同时读取多条指令&#xff0c;同时每周期也可能有多条load/store指令会访问Cache&#xff0c;因此需要多端口的Cache L1 Cache&#xff1a;最靠近处理器&#xff0c;是流水线的一部分&#xff0c;包含两个物理存在 指…...

国产版Sora复现——智谱AI开源CogVideoX-2b 本地部署复现实践教程

目录 一、CogVideoX简介二、CogVideoX部署实践流程2.1、创建丹摩实例2.2、配置环境和依赖2.3、上传模型与配置文件2.4、开始运行 最后 一、CogVideoX简介 智谱AI在8月6日宣布了一个令人兴奋的消息&#xff1a;他们将开源视频生成模型CogVideoX。目前&#xff0c;其提示词上限为…...

怎么读取FRM、MYD、MYI数据文件

一、介绍frm、MYD、MYI文件 在MySQL中&#xff0c;使用MyISAM存储引擎时&#xff0c;数据库表会被分割成几个不同的文件文件描述功能扩展名FRM 文件表结构定义文件存储表的结构信息&#xff0c;字段、索引等.FRMMYD 文件数据文件包含表的实际数据.MYD&#xff08;MYData&#x…...

Leetcode3226. 使两个整数相等的位更改次数

Every day a Leetcode 题目来源&#xff1a;3226. 使两个整数相等的位更改次数 解法1&#xff1a;位运算 从集合的角度理解&#xff0c;k 必须是 n 的子集。如果不是&#xff0c;返回 −1。怎么用位运算判断&#xff0c;见上面的文章链接。 如果 k 是 n 的子集&#xff0c;…...

Linux笔记-3()

目录 一、Linuⅸ实操篇-定时任务调度 二、Linuⅸ实操篇-Linuⅸ磁盘分区、挂载 三、Linux实操篇-网络配置 一、Linuⅸ实操篇-定时任务调度 1 crond任务调度---crontab进行定时任务的设置1.1 概述任务调度&#xff1a;是指系统在某个时间执行的特定的命令或程序。任务调度分类…...

Apache漏洞复现CVE-2021-41773

Apache HTTP Server 路径穿越漏洞 漏洞简介 该漏洞是由于Apache HTTP Server 2.4.49版本存在目录穿越漏洞,在路径穿越目录 <Directory/>Require all granted</Directory>允许被访问的的情况下&#xff08;默认开启&#xff09;&#xff0c;攻击者可利用该路径穿越…...

GIT如何将远程指定分支的指定提交拉回到本地分支

一、当前我的代码在这个提交&#xff0c;但可以看到远程仓库上面还有两次新的提交 二、现在我想让我本次的代码更新到最上面这个最新的提交 三、输入git fetch命令获取远程分支的最新提交信息。 四、输入 git log origin/<remote_branch_name>查看并找到想要更新的指定提…...

鸿蒙图形开发【3D引擎接口示例】

介绍 本实例主要介绍3D引擎提供的接口功能。提供了ohos.graphics.scene中接口的功能演示。 3D引擎渲染的画面会被显示在Component3D这一控件中。点击按钮触发不同的功能&#xff0c;用户可以观察渲染画面的改变。 效果预览 使用说明 在主界面&#xff0c;可以点击按钮进入不…...

C#实现数据采集系统-系统优化服务封装

系统优化-服务封装 现在我们调用modbustcp和mqtt都直接在Program,所有加载和功能都混合在一起,比较难以维护 类似asp.net core项目的Program.cs代码如下,构建服务配置和启动 要实现的效果,Main方法中就是一个服务启动,只需要几行代码 分析代码 这里分成两部分,一…...

数据结构与算法--栈、队列篇

一、计算机领域的地位 在计算机科学的广袤领域中&#xff0c;数据结构犹如一座精巧的大厦&#xff0c;为信息的存储和处理提供了坚实的框架。而在众多的数据结构中&#xff0c;栈和队列宛如两颗璀璨的明珠&#xff0c;各自闪耀着独特的光芒。 栈和队列虽然看似简单&…...

【程序、游戏、人生】致敬飞逝的3年和新的开始

人&#xff0c;总要向前看。 感谢之前关注的朋友&#xff0c;感谢各位朋友的私信、感谢关心的评论。 不要停下 20年&#xff1a;某银行业务三方开发。 21年&#xff1a;移动内部业务平台开发移动物联网商城开发储备TPL。 22年-至今&#xff1a;手游发行技术综合北漂 经历了行…...

第三届人工智能、人机交互与机器人国际会议

国际人工智能、人机交互和机器人会议是一项年度活动&#xff0c;汇集了来自世界各地的研究人员、从业者和行业专业人士&#xff0c;分享他们在人工智能、人际交互和机器人领域的知识和专业知识。在过去的几十年里&#xff0c;这些领域在计算能力、数据分析和机器学习技术的进步…...

AWS生成式AI项目的全生命周期管理

随着人工智能技术的迅速发展&#xff0c;生成式 AI 已成为当今最具创新性和影响力的领域之一。生成式 AI 能够创建新的内容&#xff0c;如文本、图像、音频等&#xff0c;具有广泛的应用前景&#xff0c;如自然语言处理、计算机视觉、创意设计等。然而&#xff0c;构建一个成功…...

windows go grpc

windows环境安装go grpc 的工具和插件 在Windows环境下&#xff0c;安装Protocol Buffers&#xff08;proto&#xff09;和gRPC相关的工具和插件&#xff0c;可以通过以下几个步骤进行 1.安装protoc 在git 仓库下载tag 包 https://github.com/protocolbuffers/protobuf/rele…...

Leetcode 第 135 场双周赛题解

Leetcode 第 135 场双周赛题解 Leetcode 第 135 场双周赛题解题目1&#xff1a;3222. 求出硬币游戏的赢家思路代码复杂度分析 题目2&#xff1a;3223. 操作后字符串的最短长度思路代码复杂度分析 题目3&#xff1a;3224. 使差值相等的最少数组改动次数思路代码复杂度分析 题目4…...

rpc的原理

RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;是一种编程模型&#xff0c;它允许开发者像调用本地函数一样调用位于不同进程或者不同机器上的函数或服务。这种抽象简化了分布式系统的开发&#xff0c;使得开发人员无需关注底层网络通信细节&#…...

【无线通信发展史-第二篇】,带你走进查利·奥古斯丁·库仑的世界,了解(库伦定律)-(扭秤实验)-(如何测量出静电力常量)

前言&#xff1a;用这几个问答形式来解读下我这个系列的来龙去脉。如果大家觉得本篇文章不水的话希望帮忙点赞收藏加关注&#xff0c;你们的鼓舞是我继续更新的动力。 我为什么会写这个系列呢&#xff1f; 首先肯定是因为我本身就是一名从业通信者&#xff0c;想着更加了解自…...

CAPL使用结构体的方式组装一条DoIP车辆声明消息(方法2)

在文章CAPL使用结构体的方式组装一条DoIP车辆声明消息(方法1)中,我们声明一个结构体DoIPMessage表示完整的DoIP车辆声明消息: 上半部分是DoIP报头通用部分(也就是所有类型的DoIP消息都有的),而payload是每个类型的DoIP消息独有的部分,对于车辆声明消息来说,用另一个结…...

基于Matlab的车牌识别系统设计与实现

基于Matlab的车牌识别系统设计与实现 摘要 随着智能交通系统的不断演进&#xff0c;车牌识别技术已成为提升交通管理效率与准确性的关键。本文深入探讨了基于Matlab平台的车牌识别系统设计与实现&#xff0c;该系统通过精细的图像预处理、高效的车牌定位算法、精准的字符分割…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...