Spring事件处理

news2024/11/17 13:29:49

        在实际业务开发中,有时候复杂性的业务之间需要解耦,常用的方法:同步、异步、MQ。但 MQ 重啊,非必要不提升架构复杂度。

        针对同步和异步使用方式:1.定时器 2.Spring Event.

        Spring Event:

                观察者设计模式,一个 Bean 处理完成任务后希望通知其它 Bean 或者说一个 Bean监听另一个Bean 的行为。

配置异步线程池

package com.lean.event.demo.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
public class AsynConfig implements AsyncConfigurer {

    private static final Logger log= LoggerFactory.getLogger(AsynConfig.class);

    @Bean("taskAsyncPool")
    public Executor orderTaskAsyncPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10); // 核心线程数
        executor.setMaxPoolSize(20); // 最大线程数
        executor.setQueueCapacity(1000); // 队列大小
        executor.setKeepAliveSeconds(300); // 线程最大空闲时间
        executor.setThreadNamePrefix("async-Executor-"); // 指定用于新创建的线程名称的前缀。
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略(一共四种,此处省略)
        executor.initialize();
        return executor;
    }

    @Override
    public Executor getAsyncExecutor() {
        return orderTaskAsyncPool();
    }

    // 异常处理器
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) -> log.error(String.format("执行异步任务'%s'", method), ex);
    }
}

1.同步

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.context.ApplicationEvent;
/**
 * 自定义事件 继承ApplicationEvent
 */
@Getter
@Setter
@ToString
public class MessageEvent extends ApplicationEvent {
    //传输的数据对象
    private String messageId;
    public MessageEvent(Object source, String messageId) {
        super(source);
        this.messageId = messageId;
    }
}
package com.lean.event.demo.listener;


import com.lean.event.demo.events.MessageEvent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
 * 同步
 * 监听器:
 * 实现方式:
 *      1.实现ApplicationListener
 *      2.@EventListener
 */
@Slf4j
@Component
public class MessageListener implements ApplicationListener<MessageEvent> {
    @SneakyThrows
    @Override
    public void onApplicationEvent(MessageEvent event) {
        String messageId = event.getMessageId();
        long start = System.currentTimeMillis();
        long end = System.currentTimeMillis();
        log.info("{}:耗时:({})毫秒", messageId, (end - start));
    }
}

2.异步

| 自定义事件

import lombok.AllArgsConstructor;
import lombok.Data;


@Data
@AllArgsConstructor
public class MsgEvent {
    /**
     * 该类型事件携带的信息
     */
    public String messageId;
}
import com.lean.event.demo.events.MsgEvent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class MsgListener {

    //异步注解 需要开启@EnableAsync异步
    @Async(value = "taskAsyncPool")
    @SneakyThrows
    @EventListener(MsgEvent.class)
    public void sendMsg(MsgEvent event) {
        String messageId = event.getMessageId();
        long start = System.currentTimeMillis();
        log.info("开发发送短信");
        log.info("开发发送邮件");
        long end = System.currentTimeMillis();
        log.info("{}:发送短信、邮件耗时:({})毫秒", messageId, (end - start));
    }
}
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@EnableAsync
@SpringBootApplication
public class SpringLeanEventApplication {

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

}

3.测试

package com.lean.event.demo.service;

import com.lean.event.demo.events.MsgEvent;
import com.lean.event.demo.events.MessageEvent;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@Data
public class MessageService {
    /** 注入ApplicationContext用来发布事件 */
    private final ApplicationContext applicationContext;
    public String testMessage(String messageId) {
        long start = System.currentTimeMillis();
        // (同步处理)
        applicationContext.publishEvent(new MessageEvent(this, messageId));
        // (异步处理)
        applicationContext.publishEvent(new MsgEvent(messageId));
        long end = System.currentTimeMillis();
        log.info("任务全部完成,总耗时:({})毫秒", end - start);
        return "购买成功";
    }
}

package com.lean.event.demo;


import com.lean.event.demo.service.MessageService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class MessageServiceTest {

    @Autowired
    private MessageService messageService;
    @Test
    public void buyOrderTest() {
        messageService.testMessage("123456");
    }
}

ApplicationEvent: 

类的注释是,被应用事件继承的类,抽象的不能初始化;

 EventObject: 父类

 事件携带一个 Objecgt 对象,可以被发布。

事件监听者,监听到这个事件后,触发自定义逻辑 ( 操作 Object 对象);

注意:

        事件发布后,都会被监听ApplicationEvent的监听对象所监听到。

代码

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

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

相关文章

网站反爬指南:政府网站篇

目录 前言 黑灰产为何盯上政务网站&#xff1f; 如何反爬&#xff1f; 前言 网络爬虫正在成为政务网站们最大的威胁之一。 随着网络安全被提升到国家层面&#xff0c;网站安全管理和防护日趋重要&#xff0c;政务网站既要确保网站信息的及时和准确&#xff0c;又要能应对网络…

15. Spring事务管理

1. Spring事务简介 事务作用&#xff1a;在数据层保障一系列的数据库操作同成功同失败Spring事务作用&#xff1a;在数据层或**业务层**保障一系列的数据库操作同成功同失败 2. 案例 2.1 需求和分析 需求&#xff1a;实现任意两个账户间转账操作需求微缩&#xff1a;A账户减…

如何使用 SAP OData 服务向 ABAP 服务器上传文件试读版

本教程到目前为止开发的 OData 图书管理服务&#xff0c;可以在 ABAP 系统里对图书数据进行增删改查。 本步骤我们继续介绍如何通过 SAP OData 服务&#xff0c;实现向 ABAP 系统上传文件的需求。我们采取 Postman 进行文件上传。 先看一下通过本文介绍的步骤&#xff0c;实现…

word基础功能应用:带圈字符如此妙法,好玩有趣

很多人把Word当成码字的记事本&#xff0c;其实它的逆天操作&#xff0c;远比你想象得还要强大。比如&#xff0c;Word中的“带圈字符”功能。 01、基本用法 Word中&#xff0c;点击【开始】-【带圈字符】按钮&#xff0c;即可启用“带圈字符”功能。 比如&#xff0c;我们可…

自然语言处理学习笔记-lecture10-机器翻译01

机器翻译的产生与发展 机器翻译 (machine translation, MT) 是用计算机把一种语言(源语言, source language) 翻译成另一种语言(目标语言, target language) 的一门学科和技术。 机器翻译的困难如下&#xff1a; 自然语言中普遍存在的歧义和未知现象机器翻译不仅仅是字符串的…

Spring IOC和Bean生命周期以及源码分析

这篇文章主要讲解 IOC 容器的创建过程&#xff0c;让大家对整体有一个全局的认识,文章目录如图: 1. 基础知识 1.1 什么是 Spring IOC &#xff1f; IOC 不是一种技术&#xff0c;只是一种思想&#xff0c;一个重要的面向对象编程的法则&#xff0c;它能指导我们如何设计出松耦…

springboot小区物业管理系统maven idea1562

本小区物业管理系统以springboot作为框架&#xff0c;以MySql作为后台运行的数据库&#xff0c;使用Tomcat用为系统的服务器&#xff0c;同时使用JSP显示业主界面。本系统主要包括以下功能模块&#xff1a;个人中心、业主管理、费用缴纳管理、疫情防控管理、小区车位管理、车位…

基于 Traefik 的 Basic Auth 配置

前言 Traefik是一个现代的HTTP反向代理和负载均衡器&#xff0c;使部署微服务变得容易。 Traefik可以与现有的多种基础设施组件&#xff08;Docker、Swarm模式、Kubernetes、Marathon、Consul、Etcd、Rancher、Amazon ECS...&#xff09;集成&#xff0c;并自动和动态地配置自…

Allegro如何快速统计串阻前后端的长度操作指导

Allegro如何快速统计串阻前后端的长度操作指导 Allegro可以快捷的统计出串阻前后端的长度,并且归一到一个网络中,方便查看 比如需要统计1-3的总长 具体操作如下 选择Analyze-Model Assignment出现SI Design Audit窗口,直接点击ok<

CSS -- CSS3中3D转换相关属性讲解(translate3d,rotate3d,perspective,transform-style)

文章目录3D转换1 三维坐标系2 3D移动 translate3d3 透视 perspective4 3D 旋转 rotate3d5 3D旋转 rotate3d6 3D呈现 transform-style7 3D案例3D转换 我们生活的环境是3D的&#xff0c;照片就是3D物体在2D平面呈现的例子。 3D特点&#xff1a; 近大远小。物体后面遮挡不可见 …

[论文阅读] PointSeg: Real-Time Semantic Segmentation Based on 3D LiDAR Point Cloud

文章目录1. 主要思想2. 具体方法2.1 数据投影2.2 网络结构3. 实验支撑4. 总结启示5. 相关文献paper 原论文的链接 code: 源代码链接 67.4 (car) 19.2(ped) 32.7(cyclist)|90 fps/GPU 1. 主要思想 通过什么方式&#xff0c;解决了什么问题 在SqueezeSeg的基础上&#xff0c;利用…

小学生C++编程基础 课程8(A)

912.买水果 (课程8&#xff09; 登录 913.1或2 (课程8&#xff09; 登录 914.and和or &#xff08;课程8&#xff09; 难度&#xff1a;1 登录 915.在区间里 ( 课程8 ) 难度&#xff1a;1 登录 916.区间交集 ( 课程8 ) 难度&#xff1a;1 登录 917.区间并集 ( 课程8 ) 难度…

zabbix“专家坐诊”第178期问答汇总

大家好&#xff0c;我是乐乐。早在三年前&#xff0c;我们就在社区举办了zabbix公益问答活动&#xff0c;并且定在每周三邀请资深的zabbix技术工程师&#xff0c;为社群的小伙伴进行免费的答疑。到现在已经178期了。后续我将会把每期的答疑汇总分享在百家&#xff0c;供广大的z…

Qt——基本介绍、详解对象树

目录 一.基本介绍 二.对象树 一.基本介绍 创建qt项目是&#xff0c;如果选择空窗口QWidget&#xff0c;那么mian函数中会有如下代码&#xff1a; #include "myWindow.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, ar…

【微服务】Nacos为什么丢弃短连接(http)而选择拥抱长连接(gRPC)

目录 一、现状背景 二、场景分析 1、配置 2、服务 三、长连接核心诉求 1、功能性诉求 1.1、客户端 1.2、服务端 2、性能 3、负载均衡 4、连接生命周期 4.1、心跳保活机制 4.2、需要什么 四、长连接选型对比 五、基于长链接的⼀致性模型 1.、配置⼀致性模型 1.…

Unity导出并制作window安装程序exe

前言 如果我们是做pc端游或者基于pc的一些应用的&#xff0c;那么我们肯定对打包exe应用程序不陌生&#xff0c;我们经常会用到一些软件&#xff0c;比如&#xff1a;inno setup&#xff0c;NSIS等 而使用unity做游戏开发的的人来说&#xff0c;一般导出程序都是面向手机的apk…

比亚迪艰难的国际化之路

来源:猛兽财经 作者&#xff1a;猛兽财经 比亚迪是如何在中国市场取得成功的&#xff1f; 在深入分析比亚迪&#xff08;01211&#xff09;的国际化之前&#xff0c;我们有必要先了解一下比亚迪是如何在国内市场取得成功的。为了说明这一点&#xff0c;猛兽财经将在接下来进行…

【评测】扩散流完整性测试原理

早在1997 年出台的21 CFR Part 11中&#xff0c;就对与药物产品审批放行相关的电子记录有规定&#xff0c;应采取与纸质记录相同的控制要求1&#xff0c;包括生成或维护电子记录须采用恰当的访问控制措施&#xff0c;记录变更必须体现在记录审计追踪中等。 2003年&#xff0c;…

深度理解go中的Map

这里写自定义目录标题前言map的内存模型增量扩容查找过程分析插入过程分析前言 本篇将从底层讲解map的赋值、删除、查询、扩容的具体执行过程。结合源码&#xff0c;让你彻底明白map的原理。 map的内存模型 在源码中&#xff0c;表示map的结构体是hmap&#xff0c;其定义如下…

红队隧道应用篇之Burpsuite设置上游代理访问内网(五)

为何要设置上层代理 Burp Suite设置上游代理的主要原因是为了拦截和修改来自浏览器的请求。当您在使用Burp Suite进行Web应用程序安全测试时&#xff0c;您可能希望模拟攻击者发送恶意请求&#xff0c;以测试应用程序是否能够防御这些攻击。使用上游代理可以帮助您在浏览器和目…