首页 > 其他分享 >Springboot异步事件配置和使用

Springboot异步事件配置和使用

时间:2024-10-23 17:43:10浏览次数:1  
标签:异步 Springboot 配置 public 线程 事件 注解 监听

Spring中提供了完整的事件处理机制,本身底层内置实现了一些事件和监听,同时支持开发者扩展自己的事件和监听实现。

一般这种基于事件的实现在项目实际开发中我们主要用来解耦,和做异步处理(默认是同步),提供应用的响应速度。

核心架构

先简要看一下,在Spring中要实现自定义事件监听需要涉及哪些接口类,这里忽略异步的引用、注解的实现,后面会说到。

image

基本实现步骤

  1. 自定义事件:一般继承自ApplicationEvent即可,注意里面要去定义和实现自己的事件方法,也就是具体这个事件要做什么事,一般就在事件类、或者基于事件类去实现即可。
  2. 事件发布:业务代码中注入ApplicationEventPublisher类,然后再具体业务方法中调用publishEvent方法,传入上面自定义的事件,以及自定义的必要参数等信息
  3. 实现事件监听:有了事件、也发布了,那必须有对应的监听来调用具体的事件,一般实现ApplicationListener泛型传入自己的事件类型即可

注意事项

  1. 异常和事物:默认情况下事件的发布、监听处理都是和当前业务线程绑定到一起的,也就是在同一个线程中操作事件任务。因此无论是事件发布时导致异常,或者是具体事件任务实现的方法异常,都会导致当前业务异常;相应的如果当前业务有事物,那么异常了也会回滚。
  2. 事件类型:首先一定要自定义自己的事件,其次在监听的时候也是监听自己的事件,而不是监听基类或者接口然后去判断,这样反而失去了基于事件监听编程灵活性,同时也违法开闭原则,并不利于后期扩展。具体事件中可以定义其他一些额外的参数,这样方便在具体方法中传参使用
  3. 事件顺序:一次可以发布多个事件,无论是同一个还是不同的,执行顺序默认也是按照发布顺序。

场景应用

这里以订单完成和推送给平台订单相关数据为业务模型来举例说明。Spring4.2之后提供了注解来实现事件监听,非常的方便,这里我们使用注解的方式实现监听即可。

  • 缩略的业务类:包含事件的发布
@Resource
private ApplicationEventPublisher publisher;

public void completeTrade(TradeOrder trade){
  tradeMapper.modifyStatus(trade);
  publisher.publishEvent(new TradeStatusEvent(this,new TradeStatusEvent.Params(trade,"完成订单")));
}
  • 具体事件的定义:继承自ApplicationEvent
public class TradeStatusEvent extends ApplicationEvent {
    private static final Logger logger = LoggerFactory.getLogger(TradeStatusEvent.class);

    private Params params;
    
    public Params getParams(){
      return this.params;
    }
    
    public TradeStatusEvent(Object source,Params param) {
        super(source);
        this.param = param;
    }
    
    public void send(){
      try{
        HttpUtils.send("xx.oo", PlatformBean.Builder().note(this.params.note)..build());
      } catch(Exception e){
        logger.error("TradeStatusEvent处理异常:",e);
      } 
    }
    
    
    public static class Params {
        private TradeOrder trade;
        private String note;
        //get、set 定义其他参数等
    }
}
  • 监听实现:使用注解,注意这里我使用了 事务监听注解 ,按照具体业务场景可以选择具体的注解,比如最常用的@EventListener。因为我这里的诉求是当前事物提交完成之后再去推送消息,而且实际情况是启用了异步监听来实现,同时有的人在监听的方法中可能还执行了回查,也就是去查询业务中提交的数据,那如果这里不标记为事物提交之后执行,在异步情况下无法获取到数据
@Component
public class TradeStatusEventListener {

    @TransactionalEventListener(phase= TransactionPhase.AFTER_COMMIT, fallbackExecution=true)
    void handlerAfterComplete(TradeStatusEvent event) {
        event.send();
    }
}

异步实现

所谓异步实现,一般是指异步监听,将主体业务逻辑和消息监听任务放到不同的线程去执行,提高业务的响应速度。

Springboot中我们有多个办法来实现异步监听执行,最简单、最直接的就和异步方法实现一模一样,只需在监听方法上加上@Async注解(前提是启用了异步执行)

  • 第一种办法:Configuration配置类中加上注解@EnableAsync,启用Spring的异步方法执行能力。然后在监听方法上加上@Async注解,标明此方法是异步执行。Over就这样就行了【我们没有配置异步线程对不对?那是会直接new Thread()来执行异步任务吗,当然不是,而是Spring默认提供并初始化了一个专门用来执行异步任务的线程池ThreadPoolTaskExecutor,会接管所有的异步任务在同一个线程池中执行。也支持定制化处理,后续我们会说到】
@Configuration
@EnableAsync
public class AppConfig{}
//````
@Component
public class TradeStatusEventListener {

    @Async
    @TransactionalEventListener(phase= TransactionPhase.AFTER_COMMIT, fallbackExecution=true)
    void handlerAfterComplete(TradeStatusEvent event) {
        event.send();
    }
}
  • 第二种办法:如果说不想全局开启异步,只是想给事件监听的代码实现异步任务呢?那最简单就是直接在监听哪里new Thread().start(),不受控、不优雅,但是业务场景简单,访问量小的情况下也不是不可以。那要规范一点呢,就是自己创建一个线程池,比如ExecutorService executorService = Executors.newCachedThreadPool();然后在event.send哪里使用executorService.execute(..)执行即可。
  • 第三种办法:优雅点实现,创建SimpleApplicationEventMulticaster的Bean,然后创建一个线程池给塞进去,注意需要把自定义实现注入到Spring容器中。其他代码不用做任何修改,就像同步逻辑一样,在事件发布的时候广播会使用multicastEvent调用taskExecutor获取一个线程去执行监听任务
@Configuration
public class AppConfig{
  @Bean
  public SimpleApplicationEventMulticaster simpleApplicationEventMulticaster(){
        SimpleApplicationEventMulticaster mu = new SimpleApplicationEventMulticaster();
        //这里我使用spring提供的任务构造器创建了一个立即执行的有界队列任务线程池
        Executor taskExecutor = new TaskExecutorBuilder().corePoolSize(8).maxPoolSize(200).queueCapacity(20).threadNamePrefix("trade-send-").build();
        mu.setTaskExecutor(taskExecutor);
        //设置异常处理
        mu.setErrorHandler((t)->{
            //logger.error("==========调用平台发送消息方法失败,",t);
        });
    return mu;
  }
}

框架原理

  • 为什么异步监听只需要@EnableAsync、以及在方法上加上@Async就可以了呢?
    • 当我们使用Springboot,引入starter时会自动引入spring-boot-autoconfigure,此包里面实现了很多自动配置的功能(约定大于配置)名字都是xxxAutoConfiguration,比如我们这里要说的就是TaskExecutionAutoConfiguration,容器启动的时候就会加载和创建默认的任务线程池,可以通过spring.task.execution开头属性来配置。需要注意的是,无论是否加入@EnableAsync注解TaskExecutionAutoConfiguration都会初始化一个默认的线程池,因为这个是全局的。
      image

    • @EnableAsync的作用是在容器启动的时候,告诉Spring我可要支持异步处理任务了,你看着办。Spring所好的朋友,我给你准备了一个专门搞事的拦截器。
      image

    • 当我们加入了注解,Spring会将按照配置将准备工作全部做完,从而做到开箱即用,直接一步到位。

总结

  • Spring事件模型的四个核心:事件源也就是业务方、事件、广播器、监听器
  • 事件机制支持同步、异步,按需调整和使用。使用异步监听时,推荐使用线程池管理线程,高效、稳定而且易于维护。
  • 使用Springboot时通过注解的方式监听、启用异步尽享丝滑。实际原理核心就是观察者模式。

标签:异步,Springboot,配置,public,线程,事件,注解,监听
From: https://www.cnblogs.com/Nuwa/p/18497942

相关文章

  • OpenSSL异步模式流程梳理
    源码来源于OpenSSLMasterCommitIDd550d2aae531c6fa2e10b1a30d2acdf373663889。总览核心入口函数为ssl_start_async_job,以SSL_do_handshake为入口举例分析,同时通过标注步骤【1~N】,来明确阅读的顺序。步骤【1】到步骤【18】为一个阶段步骤【19】到步骤【23】为一个阶......
  • MacOS 同时配置github、gitee和gitlab密钥
    MacOS同时配置github、gitee和gitlab密钥1在终端中新建~/.ssh目录1.1生成GitHub、Gitee和Gitlab的SSH密钥对ssh-keygen-ted25519-C"[email protected]"-f~/.ssh/id_ed25519_giteessh-keygen-ted25519-C"[email protected]"-f~/.ssh/id_ed25519_githubssh-keyge......
  • Vite 优化配置方案
    前言Vite是一个快速的前端构建工具,特别适用于现代前端框架如Vue和React。为了进一步提升项目的性能和开发体验,我们可以对Vite进行一些优化配置。本文将介绍一些常见的优化策略,并提供详细的配置示例和注释。1.安装必要的插件首先,我们需要安装一些常用的Vite插件来帮......
  • java基于springboot的中药材进存销管理系统(源码+vue+部署文档+前后端分离等)
    收藏关注不迷路!!......
  • ssts-hospital-web-master项目实战记录四:主要配置
    记录时间:2024-10-231.配置浏览器自动打开配置文件:package.json "scripts":{  "dev":"vite--open" } 2.配置src别名(1)安装@types/node输入npm命令npm i@types/node--save-dev(2)配置文件:vite.config.tsimport{defineConfig}from'vi......
  • 生产环境中raid实际配置
    生产环境中raid实际配置如果对运维课程感兴趣,可以在b站上、csdn或微信视频号上搜索我的账号:运维实战课程,可以关注我,学习更多免费的运维实战技术视频项目1.Raid实际配置:(DELLR710)启动服务器——根据提示按ctrl+R(当dell界面过去时同时按crtl+R)进入raid配置界面,如下图:根......
  • springboot集成hnlp
    基本功能添加maven依赖即可使用由字构词,依存句法分析之外的全部功能。<dependency><groupId>com.hankcs</groupId><artifactId>hanlp</artifactId><version>portable-1.8.4</version></dependency>自定义下载数据包和配置文件官方原版:        d......
  • Springboot车辆充电桩管理系统的设计与实现mv56d(程序+源码+数据库+调试部署+开发环境)
    系统程序文件列表项目功能:用户,员工,电桩类别,充电桩,报修信息,报修处理开题报告内容Springboot车辆充电桩管理系统的设计与实现开题报告一、研究背景与意义随着电动汽车的快速发展和普及,充电桩作为电动汽车的重要配套设施,其数量和管理效率直接影响到电动汽车的推广和使......
  • Springboot车辆充电桩3l3fa(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
    系统程序文件列表项目功能:用户,电桩类别,充电桩,充电桩报修,维修员,维修回复开题报告内容Springboot车辆充电桩管理系统开题报告一、研究背景随着电动汽车的普及和推广,充电桩作为电动汽车的主要充电设备,在城市中得到了广泛的应用。然而,目前存在着充电桩数量不足、充电速......
  • tomcat从安装到配置全过程(外加servlet炸包添加方法)
    tomcat写这篇笔记的原因很简单:今天脑海中冒出tomcat配置和servlet配置的问题,记不太清了,就像找找笔记,我明明记得之前记过相关的笔记,就是再笔记里面找不到了,只好重新梳理归纳一下了!一、tomcat启动后首页访问问题1.项目初始创建的jsp文件删除,会导致启动后首页出现404错误二、To......