【Java】SpringBoot实现事件监听(异步执行)

news2024/11/24 17:04:46

        在Spring Boot中,事件监听是一种机制,通过该机制,你可以定义和触发自定义的事件,以及在应用程序中注册监听器来响应这些事件,提供了一种解耦的方式来处理应用程序中的事件。

文末有源码gitee地址!拉取可进行测试。

事件监听的主要组件包括:

  1. 事件(Event):

    • 事件是一个普通的Java对象,用于封装与应用程序中发生的某个动作或状态变化相关的信息。
  2. 事件发布器(Event Publisher):

    • 事件发布器是一个负责将事件发布给注册的监听器的组件。在Spring中,ApplicationEventPublisher接口定义了事件发布器的标准。
  3. 事件监听器(Event Listener):

    • 事件监听器是用于监听和响应特定事件的组件。在Spring中,通过ApplicationListener接口或使用@EventListener注解来定义事件监听器。

在Spring Boot中实现事件监听的步骤如下:

  1. 定义事件类:

    • 创建一个普通的Java类,用于表示特定的事件。该类通常继承自ApplicationEvent或其子类。
  2. 定义事件发布器(可选):

    • 可以在需要的地方注入ApplicationEventPublisher并使用它来发布事件,或者直接通过Spring容器(ApplicationContext)发布事件。
  3. 定义事件监听器:

    • 创建一个实现ApplicationListener接口或使用@EventListener注解的类,用于监听特定的事件,并在事件发生时执行相应的逻辑。
  4. 注册监听器:

    • 将事件监听器注册到Spring容器中,可以通过注解、Java配置或XML配置来完成。

以下是一个简单的示例,演示了如何在Spring Boot中实现事件监听(主要代码展示):

代码层级结构:

1.自定义事件类 CoursesTestEvent继承ApplicationEvent

package com.example.springbootredis.event;

import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;

/**
 * 课程事件类,继承自 ApplicationEvent,表示课程相关的事件。
 */
@Setter
@Getter
public class CoursesTestEvent extends ApplicationEvent {

    private Integer id;
    /**
     * 课程标题
     */
    private String title;
    /**
     * 课程封面
     */
    private String thumb;
    /**
     * 课程价格(分)
     */
    private Integer charge;
    /**
     * 随便传递几个参数
     * */
    public CoursesTestEvent(Object source, String title, String thumb) {
        super(source);
        this.title = title;
        this.thumb = thumb;
    }

}

2.创建一个事件监听器类 CoursesTestListener:

package com.example.springbootredis.listener;

import com.example.springbootredis.event.CoursesTestEvent;
import com.example.springbootredis.service.CoursesService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * 用于测试监听事务,异步执行方法
 * 课程事件监听器类,用于异步更新课程信息。
 */
@Component
@Slf4j
public class CoursesTestListener {

    //根据实际的需求进行注入
    @Autowired
    private CoursesService coursesService;

    /**
     * 异步事件监听方法,用于监听CoursesTestEvent进行更新课程相关信息。
     * @param event 触发的课程的事件。
     */
//    @Async("myTaskExecutor") // 异步执行的注解,线程池
//    @Async() // 异步执行的注解
    @EventListener  // 事件监听器的注解
    public void updateLoginInfo(CoursesTestEvent event)  {
        //检查是否能够获取到CoursesTestEvent
        System.out.println("title:"+event.getTitle());
        System.out.println("thumb:"+event.getThumb());
        System.out.println(3);
        // 打印当前线程的信息
        System.out.println("执行当前线程的名称3: " + Thread.currentThread().getName());
    }
}

3.在业务逻辑中进行测试事件监听:

package com.example.springbootredis.service.impl;

import com.example.springbootredis.domain.Courses;
import com.example.springbootredis.event.CoursesTestEvent;
import com.example.springbootredis.mapper.CoursesMapper;
import com.example.springbootredis.service.CoursesService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
@Slf4j
public class CoursesServiceImpl implements CoursesService {

    @Autowired
    private CoursesMapper coursesMapper;

    //用于管理和维护Bean以及处理Bean之间依赖关系的核心容器。
    @Autowired
    private ApplicationContext applicationContext;

    //进行异步测试
    @Override
    public List<Courses> asyTest() {

        List<Courses> courses = coursesMapper.findAll();
        System.out.println(1);
        // 打印当前线程的信息
        System.out.println("执行当前线程的名称1: " + Thread.currentThread().getName());
        // 发布自定义的课程测试事件
        applicationContext.publishEvent(new CoursesTestEvent(this,courses.get(0).getTitle(),courses.get(0).getThumb()));
        System.out.println(2);
        System.out.println("执行当前线程的名称2: " + Thread.currentThread().getName());
        return courses;
    }

}

4.代码执行结果(没有使用异步):

测试达到了监听的效果了,但是都是同一个线程执行,按照顺序进行执行,没有达到异步的效果。为了增加响应的效率,对监听事件进行异步的执行。

Spring Boot的异步任务通常使用以下几个核心注解:

    @EnableAsync:
        在Spring Boot应用程序的配置类上添加@EnableAsync注解,以启用异步任务支持。这样Spring会为异步方法创建一个代理,允许它们在单独的线程中执行。

package com.example.springbootredis;


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@MapperScan("com.example.springbootredis.mapper")
@EnableAsync //开启异步任务支持(主要)
public class SpringbootRedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootRedisApplication.class, args);
    }

}

    @Async:
        在需要异步执行的方法上添加@Async注解。这告诉Spring框架将这个方法的调用包装在一个新的线程中执行。

package com.example.springbootredis.listener;

import com.example.springbootredis.event.CoursesTestEvent;
import com.example.springbootredis.service.CoursesService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * 用于测试监听事务,异步执行方法
 * 课程事件监听器类,用于异步更新课程信息。
 */
@Component
@Slf4j
public class CoursesTestListener {

    //根据实际的需求进行注入
    @Autowired
    private CoursesService coursesService;

    /**
     * 异步事件监听方法,用于监听CoursesTestEvent进行更新课程相关信息。
     * @param event 触发的课程的事件。
     */
//    @Async("myTaskExecutor") // 异步执行的注解,线程池
    @Async() // 异步执行的注解
    @EventListener  // 事件监听器的注解
    public void updateLoginInfo(CoursesTestEvent event)  {
        //检查是否能够获取到CoursesTestEvent
        System.out.println("title:"+event.getTitle());
        System.out.println("thumb:"+event.getThumb());
        System.out.println(3);
        // 打印当前线程的信息
        System.out.println("执行当前线程的名称3: " + Thread.currentThread().getName());
    }
}

再进行测试(异步):

这样就达到异步的效果了,对监听事件进行异步执行。如果想直接进行测试,下面是gitee地址:创建一个数据库将courses.sql文件进行执行,启动即可测试:https://gitee.com/sophisticatedxin/springboot-asy-demo.git

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

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

相关文章

MySQL基础笔记(8)多表查询

一.多表关系介绍 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也会存在着各种联系&#xff0c;分为如下3类&#xff1a; 一对…

【C++提高编程(二)】

一、STL初识 1.1、STL的诞生 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西 C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升 大多情况下&#xff0c;数据结构和算法都未能有一套标准,导致被迫从事大量重复工作 为了建立数据结构和算法的一套标…

神经网络算法 —— 一文搞懂Transformer !!

文章目录 前言 一、Transformer的本质 1. Transformer架构 2. Encoder-Decoder&#xff08;编码器-解码器&#xff09; 二、Transformer的原理 1. Multi-Head Attention&#xff08;多头自注意力&#xff09; 2. Scaled Dot-Product Attention&#xff08;缩放点积注意力&#…

坦克大战游戏代码

坦克大战游戏 主函数战场面板开始界面坦克父类敌方坦克我方坦克子弹爆炸效果数据存盘及恢复图片 主函数 package cn.wenxiao.release9;import java.awt.event.ActionEvent; import java.awt.event.ActionListener;import javax.swing.JFrame; import javax.swing.JMenu; impor…

2024年【金属非金属矿山(地下矿山)安全管理人员】证考试及金属非金属矿山(地下矿山)安全管理人员模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员】证考试及金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员模拟考试题库&#xff0c;包含金属非金属矿山&#xff08;地下矿山&…

RabbitMQ-消息延迟

一、死信交换机 1、描述 一个队列接收到的消息有过期时间&#xff0c;消息过期之后&#xff0c;如果配置有死信队列&#xff0c;消息就会进去死信队列。 2、图解 3、过程 当生产者将消息发送到exchange1&#xff0c;然后交换机将消息路由到队列queue1&#xff0c;但是队列que…

探索指针的奇妙世界,程序中的魔法箭头(上)

目录 一.指针是什么二.指针和指针类型1.指针加减整数2.指针的解引用 三.野指针1.野指针形成的原因&#xff08;1&#xff09;指针未初始化指针越界访问 2.如何规避野指针&#xff08;1&#xff09;指针初始化&#xff08;2&#xff09;小心指针越界&#xff08;3&#xff09;指…

SpringSecurity+JWT前后端分离架构登录认证

目录 1. 数据库设计 2. 代码设计 登录认证过滤器 认证成功处理器AuthenticationSuccessHandler 认证失败处理器AuthenticationFailureHandler AuthenticationEntryPoint配置 AccessDeniedHandler配置 UserDetailsService配置 Token校验过滤器 登录认证过滤器接口配置…

理解PCIE设备透传

PCIE设备透传解决的是使虚拟机直接访问PCIE设备的技术&#xff0c;通常情况下&#xff0c;为了使虚拟机能够访问Hypervisor上的资源&#xff0c;QEMU&#xff0c;KVMTOOL等虚拟机工具提供了"trap and emulate"&#xff0c; Virtio半虚拟化等机制实现。但是这些实现都…

用通俗易懂的方式讲解:使用 Langchain 和 Hugging Face ,轻松实现大模型 RAG 用法

检索增强生成&#xff08;RAG&#xff09;是一种与预训练的大型语言模型&#xff08;LLM&#xff09;和自己的数据一起工作的模式&#xff0c;用于生成响应。 现在我将向大家介绍在代码中实现 RAG 的过程。让我们开始使用 Langchain 和 Hugging Face 实现 RAG&#xff01; 文章…

matlab appdesigner系列-常用14-树(复选框)

之前系列常用9&#xff0c;为单个复选框。树&#xff0c;就是多个复选框形成的选项组 示例&#xff1a;列举湖北省的几个城市 湖北省 武汉 宜昌 襄阳 荆州 1&#xff09;将树&#xff08;复选框&#xff09;拖拽到画布上&#xff0c;方式1就是&#xff1a;文字可以在右侧…

【线上问题】CompletableFuture与线程池使用不当导致服务整个挂掉

Informal Essay By English It is always a pleasure to learn 背景 在某一个风和日丽的早上&#xff0c;小组同事说昨晚线上服务有20分钟左右的不可用&#xff0c;当时内心一紧&#xff0c;不会是我写的代码有bug导致的吧&#x1f440;&#xff0c;我正了正心态&#xff0c…

[小程序]样式与配置

一、外部样式导入 使用import加外部样式表的相对路径并以 ; 表示语句结束。 import "common.wxss"; 二、全局样式和局部样式 全局样式位于app.wxss中&#xff0c;会作用于整个项目中所有页面中。 局部样式位于对应的wxss文件中&#xff0c;仅作用于当前页面&#x…

WebDriverWait太强大

selenium webdriver及wait 1 implicitly包打天下2 Linkedin无法登录返回值很乱&#xff0c;怎么破&#xff1f; 1 implicitly包打天下 有了implicitly之后&#xff0c;基本上不再关注网速之类的影响。 self.driver.implicitly_wait(511)2 Linkedin无法登录返回值很乱&#xf…

Vulnhub-TECH_SUPP0RT: 1渗透

文章目录 一、前言1、靶机ip配置2、渗透目标3、渗透概括 开始实战一、信息获取二、使用smb服务获取信息三、密码破解四、获取webshell五、反弹shell六、web配置文件获取信息七、提权 一、前言 由于在做靶机的时候&#xff0c;涉及到的渗透思路是非常的广泛&#xff0c;所以在写…

ad18报错:clearance constraint

最常见的报错&#xff0c;直译过来的意思&#xff1a;间隙约束。也就是约束PCB中的电气间距&#xff0c;比如阻容各类元件的焊盘间距小于规则中的设定值&#xff0c;即报警。 Altium Designer 中的 Clearance Constraint 错误如何修改-CSDN博客 【Altium Designer21】DRC规则…

Vulnhub靶机:FunBox 2

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;FunBox 2&#xff08;10.0.2.27&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://download.vulnhub.com/funbo…

决策树的分类

概念 决策树是一种树形结构 树中每个内部节点表示一个特征上的判断&#xff0c;每个分支代表一个判断结果的输出&#xff0c;每个叶子节点代表一种分类结果 决策树的建立过程 1.特征选择&#xff1a;选取有较强分类能力的特征。 2.决策树生成&#xff1a;根据选择的特征生…

【代码随想录07】344.反转字符串 541. 反转字符串II 05.替换空格 151.翻转字符串里的单词 55. 右旋转字符串

目录 344. 反转字符串题目描述做题思路参考代码 541. 反转字符串 II题目描述参考代码 05. 替换数字题目描述参考代码 151. 反转字符串中的单词题目描述参考代码 55. 右旋转字符串题目描述参考代码 344. 反转字符串 题目描述 编写一个函数&#xff0c;其作用是将输入的字符串反…

HTML以及CSS相关知识总结(一)

近日就开始回顾html和css相关知识啦&#xff0c;并且会学习html5和css3的新知识&#xff0c;以下是我对记忆不太深刻的地方以及新知识点的总结&#xff1a; Web标准&#xff1a; 结构&#xff1a;用于对网页元素进行整理和分类&#xff0c;即HTML 表现&#xff1a;用于设置网页…