Spring的监听机制详解

news2024/11/27 16:34:34

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 {


    @EventListener
    public 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 {
    @Autowired
    private 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 监听器使用了异步执行机制,因此不会影响主线程的运行效率,保证了应用程序的高并发和高效性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1985343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入研究scRNA-seq基础模型

基础模型在大量未标记的数据集上进行预训练&#xff0c;然后在特定任务上进行微调&#xff0c;最近基础模型在生物学应用中取得了成功。该文探讨了最近的scRNA-seq基础模型&#xff0c;scBERT和scGPT。专注于细胞类型注释的微调任务&#xff0c;主要探索了与简单基线&#xff0…

OpenCV教程04:结合pillow在图片上显示中文文字

1.如果添加的内容是纯英文文字&#xff0c;直接使用cv2.putText 函数操作即可。但它不支持自定义字体文件&#xff0c;仅限于这些内置的字体样式。如果你需要更复杂的字体支持&#xff0c;可能需要使用其他库&#xff0c;如 Python Imaging Library (PIL) 或 Pillow。可用的字体…

判断用户是否在pwa环境中打开运行?(已安装的 PWA 与未安装的 PWA 网站之间有什么区别?)以及pwa安装成功/失败的回调

前言&#xff1a; &#x1f449;vue3tsvite项目中使用vite-plugin-pwa搭建 PWA 项目&#xff0c;以及如何处理pwa安装图标的显示隐藏 &#x1f449;pwa在iframe下能否显示&#xff0c;以及在iframe下相关问题解析 如何判断用户是否在pwa环境中运行? 根据pwa配置的display-mo…

下载qwen2-72b报错

下载大模型或者是国外的大文件&#xff0c;最好配置git的代理&#xff0c;报错如下&#xff1a;https://modelscope.cn/models/qwen/Qwen2-72B 增加以下配置解决 git config --global http.sslVerify “false” git config --global advice.detachedHead false

小程序测试文档

预约小程序测试文档 一、访客 1、访客审批预约在vue修改过成功以后&#xff0c;在小程序页面未显示 解决办法 在pages\appointQuery\appointQuery.wxml页面中修改 <view class"order_right"><view class"order_status_left" wx:if"{{item…

想发Top实力不够:顶刊也能“水”!影响因子9.1 ,国人友好,2个月秒速录用

本周投稿推荐 SCI&EI • 4区“水刊”&#xff0c;纯正刊&#xff08;来稿即录&#xff09; • CCF-B类&#xff0c;IEEE一区-Top&#xff08;3天初审&#xff09; EI • 各领域沾边均可&#xff08;2天录用&#xff09; 知网&#xff08;CNKI&#xff09;、谷歌学术 …

exptern “C“的作用,在 C 和 CPP 中分别调用 openblas 中的 gemm 为例

openblas提供的sgemm有两种方式&#xff0c;一种是通过cblas&#xff0c;另一种是直接声明并调用 sgemm_ 其中&#xff0c;cblas方式是更正规调用方法&#xff1b; 1&#xff0c;调用openblas的 sgemm 的两种方式 1.1 c语言程序中使用 sgemm hello_sgemm.c #include <st…

层次分析法(评价类问题)

本文章内容来自&#xff1a;​​​​​​​ 层次分析法模型讲解(附matlab和python代码) 【数学建模快速入门】数模加油站 江北_哔哩哔哩_bilibili 一. 概念 做决策依托于量化分析&#xff0c;量化分析依托于选择的指标以及各项指标的权重&#xff08;重要性及对结果的影响程度…

XLT开关矩阵

开关矩阵 苏州新利通 系列化开关矩阵是提高被测件测试效率、实现自动化测试的核心设备&#xff0c;是基于标准控制平台可进行定制化设计的产品。系列化开关矩阵工作频率范围覆盖DC~67GHz&#xff0c;可通过LAN、GPIB、RS232和USB-B等标准控制接口&#xff0c;支持客户端、Web…

ElasticSearch安装与集群部署

ElasticSearch安装与集群部署 很多小伙伴第一次接触ElasticSearch的时候是一脸愁容,这个东西他怎么用啊,不知道从哪里安装,那我们今天就着重从哪里下载?怎么下载?怎么安装?来研究一下吧! windows下载安装ElasticSearch 下载地址&#xff1a;https://www.elastic.co/cn/do…

移动端下拉加载更多(h5,小程序)

1.h5,使用原生方式监听页面滚动下拉加载更多 <template><div></div> </template><script> export default {data() {return {loadflag: true,maxpages: 0, //最大页码currentpage: 0, //当前页listData: [],config: {page: 1,pageSize: 15,tota…

Unity开发的Domino多米诺3D小游戏源码

Unity开发的Domino多米诺3D小游戏源码下载地址

计算机组成原理 - 总线、输入/输出系统

总线 考纲内容 总线的基本概念总线的组成及性能指标总线事务和定时 本章大多以选择题的形式出现&#xff0c;特别是总线的特点、猝发传输方式、性能指标、定时方式及常见的总线标准等 思考以下问题&#xff1a; 1、引入总线结构有什么好处? 2、引入总线结构会导致什么问题…

公司官网为何建议用OV SSL证书?如何申请?

随着网络安全威胁的日益增多&#xff0c;保护用户数据安全变得尤为重要。其中SSL&#xff08;Secure Sockets Layer&#xff09;证书成为了保障网站安全的关键技术之一。而在众多SSL证书中&#xff0c;OV&#xff08;Organization Validation&#xff09;SSL证书因其独特的优势…

JVM(九)深入解析Java字节码技术与执行模型

这篇文章深入探讨了Java字节码技术&#xff0c;包括字节码的简介、获取字节码清单的方法、解读字节码清单、查看class文件中的常量池信息、查看方法信息、线程栈与字节码执行模型、方法体中的字节码解读、对象初始化指令、栈内存操作指令、局部变量表、流程控制指令、算术运算指…

读取压缩文件

读取压缩文件 1、背景 D盘下面有一个zipTest1.zip压缩文件 1.1 zipTest里面的内容 1.2 zipTest中有三个文件夹dir1、dir2、dir3 1.3 每一个文件夹下都有一个.txt文件 2、要求 读取D盘下面zipTest1.zip压缩文件里的内容到D盘下面zipTest2 3、实现 public static void main…

Go语言使用cobra开发第一个命令行程序

源码下载 本教程源码下载地址&#xff1a;https://github.com/zhangdapeng520/zdpgo_cobra_examples 案例说明 实现一个简单的命令行程序&#xff0c;能够将输入的单词转换为大写。 使用演示 执行命令&#xff1a; go run .\main.go word -u -s hello输出结果&#xff1a…

XXE靶机教学

arp-scan -l主机发现 arp-scan -l 端口扫描 nmap -p- 192.168.48.139 服务探测 nmap -p80,5355 -sT -sC -sV 192.168.48.139 目录扫描 dirsearch -u http://192.168.48.139 访问robots.txt 发现两个可访问路径 burp抓包 测试是否存在xxe漏洞 <?xml version "1.…

超声波清洗机性价比高的型号有哪些?四款值得关注的高性能超声波清洗机推荐

如果你发现眼镜变得非常脏&#xff0c;甚至出现青铜色的污渍&#xff0c;那说明是时候清洁眼镜了&#xff01;很多人往往不在意这些细节&#xff0c;结果眼镜越戴越模糊&#xff0c;实际上这主要是因为镜片上的油污、手指皮肤的残留以及生活中的灰尘积累。如果不及时清洁&#…

【实现100个unity特效之15】最简单的方法使用shader graphs实现2d树叶草的随风摇摆效果

文章目录 前言新建shader graphs新建材质效果完结 前言 本文只是实现一个简单版本的2d树叶草随风摇摆的效果&#xff0c;如果你想要实现更加复杂的效果&#xff0c;包括2d互动草&#xff0c;你可以参考我之前的文章&#xff1a; 【推荐100个unity插件之24】实现2d交互式草树叶…