在SpringBoot中添加自定义增强SpringEvent事件组件

场景说明:在使用SpringBoot时,总是要添加一大堆自定义事件,实现ApplicationEvent,来实现事件发送。

这样写代码量非常大。为了方便和避免出错,封装自定义的模块,快速实现泛型中调用SpringEvent实现事件。省去配置,简化代码,增加多线程并发处理。

一、配置自定义注解和泛型事件
1、添加自定义注解来开启配置

import org.springframework.context.annotation.Import;import java.lang.annotation.*;/*** 自动启用 Spring Event事件*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import({QySpringEventConfiguration.class})
@Documented
public @interface EnableQySpringEvent {
}

2、自定义配置中,设置线程池和注入配置

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;/*** 配置,加载EventBus事件总线*/
@Configuration
@EnableAsync // 自动开启异步处理
@Slf4j
public class QySpringEventConfiguration {private final ApplicationContext applicationContext;@Autowiredpublic QySpringEventConfiguration(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Beanpublic QyEventService qySpringEventService() {log.info("<<<<<<<<<<<<<<< 注入QyEventService实现自定义事件 >>>>>>>>>>>>>>>>>>");return new QySpringEventServiceImpl(applicationContext);}/*** 指定线程池,专用于事件订阅和发布** @return*/@Bean(name = "eventTaskExecutor")public TaskExecutor eventTaskExecutor() {ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();taskExecutor.setThreadNamePrefix("qy-springEventTaskExecutor-");taskExecutor.setCorePoolSize(5);taskExecutor.setQueueCapacity(100);taskExecutor.setMaxPoolSize(5);taskExecutor.initialize();return taskExecutor;}/*** 为SpringEvent指定线程池* 注意beanName必须为applicationEventMulticaster;下面的源码中你将看到** @param beanFactory* @return*/@Bean(name = AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)public SimpleApplicationEventMulticaster eventMulticaster(BeanFactory beanFactory) {SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);eventMulticaster.setTaskExecutor(eventTaskExecutor());return eventMulticaster;}}

3、定义支持泛型的事件,省去每次配置ApplicationEvent的过程

import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
import org.springframework.core.ResolvableType;
import org.springframework.core.ResolvableTypeProvider;/*** 带泛型的多重使用器** @param <T>*/
@Setter
@Getter
public class QyEvent<T> extends ApplicationEvent implements ResolvableTypeProvider {private T data;public QyEvent(T data) {super(data);this.data = data;}public QyEvent(Object source, T data) {super(source);this.data = data;}@Overridepublic ResolvableType getResolvableType() {return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(data));}
}

4、定义发送服务

/*** Spring内部自带的事件发布器*/
public interface QyEventService {/*** 发布事件** @param qyEvent*/<T> void publishEvent(QyEvent<T> qyEvent);}

5、服务实现类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;@Component
public class QySpringEventServiceImpl implements QyEventService {private final ApplicationContext applicationContext;@Autowiredpublic QySpringEventServiceImpl(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Overridepublic <T> void publishEvent(QyEvent<T> qyEvent) {applicationContext.publishEvent(qyEvent);}
}

更多精彩内容关注我的公众号:青塬科技。

二、在使用时
1、在入口处添加注解
@EnableQySpringEvent

2、使用时,在服务中添加

@Resource
QyEventService qyEventService;

测试发送消息内容:

IntStream.rangeClosed(0, 10).forEach(item -> {qyEventService.publishEvent(new QyEvent<>("test" + item));
});

3、添加监听器

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;/*** 事件监听处理器*/
@Component
@Slf4j
public class QyEventListener {@Async // 异步实现@EventListener // 监听器,会自动识别类型public void onOperationLogEvent(QyEvent<String> event) {log.info("QyEvent Listener recieve message: " + event.getData());}
}

日志显示:

2024-05-21 14:51:22.798  INFO 14757 --- [qy-springEventTaskExecutor-1] c.q.justtest.listener.QyEventListener    : QyEvent Listener recieve message: test5
2024-05-21 14:51:22.798  INFO 14757 --- [qy-springEventTaskExecutor-3] c.q.justtest.listener.QyEventListener    : QyEvent Listener recieve message: test3
2024-05-21 14:51:22.798  INFO 14757 --- [qy-springEventTaskExecutor-2] c.q.justtest.listener.QyEventListener    : QyEvent Listener recieve message: test4
2024-05-21 14:51:22.798  INFO 14757 --- [qy-springEventTaskExecutor-4] c.q.justtest.listener.QyEventListener    : QyEvent Listener recieve message: test6
2024-05-21 14:51:22.798  INFO 14757 --- [qy-springEventTaskExecutor-1] c.q.justtest.listener.QyEventListener    : QyEvent Listener recieve message: test7
2024-05-21 14:51:22.798  INFO 14757 --- [qy-springEventTaskExecutor-4] c.q.justtest.listener.QyEventListener    : QyEvent Listener recieve message: test1
2024-05-21 14:51:22.798  INFO 14757 --- [qy-springEventTaskExecutor-4] c.q.justtest.listener.QyEventListener    : QyEvent Listener recieve message: test8
2024-05-21 14:51:22.798  INFO 14757 --- [qy-springEventTaskExecutor-1] c.q.justtest.listener.QyEventListener    : QyEvent Listener recieve message: test9
2024-05-21 14:51:22.798  INFO 14757 --- [qy-springEventTaskExecutor-4] c.q.justtest.listener.QyEventListener    : QyEvent Listener recieve message: test2
2024-05-21 14:51:22.798  INFO 14757 --- [qy-springEventTaskExecutor-2] c.q.justtest.listener.QyEventListener    : QyEvent Listener recieve message: test0
2024-05-21 14:51:22.798  INFO 14757 --- [qy-springEventTaskExecutor-3] c.q.justtest.listener.QyEventListener    : QyEvent Listener recieve message: test10

可以发现已经实现多线程,并且并发打印出消息。

总结

关于多线程的内容已经说完了,但是我还想说点别的,主要想说一下我们应该学习哪些技术才能让它更加保值。

在我看来,越偏向于业务的技术越不容易过时,为什么呢?需求在变,技术一直在变,业务也一直在迭代。前端技术的发展非常快,也涌现出很多的框架(例如 HTML4 到 HTML5 的升级,或者从jQuery 到前端三大框架的转变),但是总归就是两个字:效率。

作为开发者,我们需要保持好奇心和学习热情,不断探索新的技术,只有这样,我们才能在这个快速发展的时代中立于不败之地。介绍一款程序员都应该知道的软件JNPF快速开发平台,很多人都尝试用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。

JNPF可以实现应用从创建、配置、开发、测试到发布、运维、升级等完整生命周期的管理。减少了传统应用程序的代码编写量,通过图形化、可视化的界面,以拖放组件的方式,即可快速生成应用程序的产品,大幅降低了开发企业管理类软件的难度。

当然,我更建议大家成为一个全栈,不要把自己的定位局限于前端。

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

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

相关文章

Xinstall助力实现App间直接跳转,提升用户体验

在移动互联网时代&#xff0c;App已成为我们日常生活中不可或缺的一部分。然而&#xff0c;在使用各类App时&#xff0c;我们经常会遇到需要在不同App之间切换的情况&#xff0c;这时如果能够直接跳转&#xff0c;将会大大提升用户体验。而Xinstall正是这样一款能够帮助开发者实…

OpenCV 获取 RTSP 摄像头视频流保存至本地

介绍 Java OpenCV 是一个强大的开源计算机视觉库&#xff0c;它提供了丰富的图像处理和分析功能&#xff0c;越来越多的应用需要使用摄像头来获取实时视频流进行处理和分析。 在 Java 中使用 OpenCV 打开摄像头的基本步骤如下&#xff1a; 确保已经安装了OpenCV库使用 OpenC…

Raylib 绘制自定义字体的一种套路

Raylib 绘制自定义字体是真的难搞。我的需求是程序可以加载多种自定义字体&#xff0c;英文中文的都有。 我调试了很久成功了&#xff01; 很有用的参考&#xff0c;建议先看一遍&#xff1a; 瞿华&#xff1a;raylib绘制中文内容 个人笔记&#xff5c;Raylib 的字体使用 - …

W801 实现获取天气情况

看了小安派&#xff08;AiPi-Eyes 天气站&#xff09;的源码&#xff0c;感觉用W801也可以实现。 一、部分源码 main.c #include "wm_include.h" #include "Lcd_Driver.h"void UserMain(void) {printf("\n user task \n");Lcd_Init();Lcd_Clea…

MySQL主从复制(五):读写分离

一主多从架构主要应用场景&#xff1a;读写分离。读写分离的主要目标是分摊主库的压力。 读写分离架构 读写分离架构一 架构一结构图&#xff1a; 这种结构模式下&#xff0c;一般会把数据库的连接信息放在客户端的连接层&#xff0c;由客户端主动做负载均衡。也就是说由客户…

RabbitMQ 消息队列安装及入门

市面常见消息队列中间件对比 技术名称吞吐量 /IO/并发时效性&#xff08;类似延迟&#xff09;消息到达时间可用性可靠性优势应用场景activemq万级高高高简单易学中小型企业、项目rabbitmq万级极高&#xff08;微秒&#xff09;高极高生态好&#xff08;基本什么语言都支持&am…

为什么MySQL推荐使用utf8mb4代替utf8?

前言 在MySQL数据库的世界里&#xff0c;字符集的选择直接影响着数据的存储和检索方式&#xff0c;尤其是对于多语言支持至关重要的应用而言。近年来&#xff0c;utf8mb4字符集逐渐成为MySQL中存储Unicode字符的标准选择&#xff0c;逐步取代了传统的utf8字符集。本文将详细探…

leetcode124 二叉树中的最大路径和-dp

题目 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根节点 root &…

【Crypto】Rabbit

文章目录 一、Rabbit解题感悟 一、Rabbit 题目提示很明显是Rabbit加密&#xff0c;直接解 小小flag&#xff0c;拿下&#xff01; 解题感悟 提示的太明显了

redis核心面试题二(实战优化)

文章目录 10. redis配置mysql实战优化[重要]11. redis之缓存击穿、缓存穿透、缓存雪崩12. redis实现分布式session 10. redis配置mysql实战优化[重要] // 最初实现OverrideTransactionalpublic Product createProduct(Product product) {productRepo.saveAndFlush(product);je…

MQTT 5.0 报文解析 05:DISCONNECT

欢迎阅读 MQTT 5.0 报文系列 的第五篇文章。在上一篇中&#xff0c;我们已经介绍了 MQTT 5.0 的 PINGREQ 和 PINGRESP 报文。现在&#xff0c;我们将介绍下一个控制报文&#xff1a;DISCONNECT。 在 MQTT 中&#xff0c;客户端和服务端可以在断开网络连接前向对端发送一个 DIS…

手把手教你搭建一个花店小程序商城

如果你是一位花店店主&#xff0c;想要为你的生意搭建一个精美的小程序商城&#xff0c;以下是你将遵循的五个步骤。 步骤1&#xff1a;登录乔拓云平台进入后台 首先&#xff0c;你需要登录乔拓云平台的后台管理页面。你可以在电脑或移动设备上的浏览器中输入乔拓云的官方网站…

2024.5.26 机器学习周报

目录 引言 Abstract 文献阅读 1、题目 2、引言 3、创新点 4、Motivation 5、naive Lite-HRNet 6、Lite-HRNet 7、实验 深度学习 解读SAM(Segment Anything Model) 1、SAM Task 2、SAM Model 2.1、Patch Embedding 2.2、Positiona Embedding 2.3、Transformer …

移动端适配:vw适配方案

vw (Viewport Width) 是一种长度单位&#xff0c;代表视口宽度的百分比。1vw 等于视口宽度的1%。在网页设计和前端开发中&#xff0c;vw 单位常用于实现响应式设计和屏幕适配&#xff0c;尤其是针对不同尺寸和分辨率的移动设备。 为什么使用vw适配&#xff1f; 响应式: 使用v…

互联网医院开发:引领智慧医疗新时代

随着科技的迅猛发展和互联网的普及&#xff0c;传统医疗模式正在迎来一场深刻的变革。互联网医院的崛起&#xff0c;打破了时间和空间的限制&#xff0c;为患者和医疗机构带来了更加便捷、高效、安全的医疗服务体验。本文将从技术角度深入探讨互联网医院的开发&#xff0c;包括…

【openpcdet中yaml文件的DATA_AUGMENTOR学习】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、代码二、详细解释DISABLE_AUG_LISTAUG_CONFIG_LIST1. gt_sampling2. random_world_flip3. random_world_rotation4. random_world_scaling 总结 前言 提示…

多线程(八)

一、wait和notify 等待 通知 机制 和join的用途类似,多个线程之间随机调度,引入 wait notify 就是为了能够从应用层面上,干预到多个不同线程代码的执行顺序.( 这里说的干预,不是影响系统的线程调度策略 内核里的线程调度,仍然是无序的. 相当于是在应用程序…

Pod容器资源限制和探针

目录 一、资源限制 1.Pod和容器的资源请求和限制 2.CPU 资源单位 案例一 案例二 二、健康检查&#xff0c;又称为探针&#xff08;Probe&#xff09; 1.探针的三种规则 2.Probe支持三种检查方法 3.探测获得的三种结果 案例一&#xff1a;exec 案例二&#xff1a;htt…

OneMO同行 心级服务:中移物联OneMO模组助力客户终端寒冷环境下的稳定运行

中移物联OneMO模组以客户为中心&#xff0c;基于中国移动心级服务要求&#xff0c;开展“OneMO同行 心级服务 标定一流”高标服务主题活动&#xff0c;升级“服务内容““服务方式”和“服务意识”&#xff0c;为行业客户提供全新的服务体验。 近日&#xff0c;某车载监控设备…

Hive语法学习总结

Hive SQL语法学习总结 hive参数库操作1.创建库2.具体案例3.库的其他操作 表和库的路径演示表的操作创建表插入数据 hive参数 一 hive常用交互命令hive -e sql语句hive -f sql文件 //文件中是sql语句二 参数的设置方式一&#xff1a;在客户端中设置参数(当次有效)set 参数名参…