当前位置:首页 > 科技  > 软件

Spring事件如何异步执行?

来源: 责编: 时间:2024-03-18 09:42:49 112观看
导读环境:SpringBoot2.7.161. 简介ApplicationContext 中的事件处理是通过 ApplicationEvent 类和 ApplicationListener 接口提供的。如果在上下文中部署了实现 ApplicationListener 接口的 Bean,那么每次 ApplicationEvent

环境:SpringBoot2.7.16JM728资讯网——每日最新资讯28at.com

1. 简介

ApplicationContext 中的事件处理是通过 ApplicationEvent 类和 ApplicationListener 接口提供的。如果在上下文中部署了实现 ApplicationListener 接口的 Bean,那么每次 ApplicationEvent 发布到 ApplicationContext 时,都会通知该 Bean。从本质上讲,这就是标准的观察者设计模式。JM728资讯网——每日最新资讯28at.com

JM728资讯网——每日最新资讯28at.com

从Spring 4.2开始,事件基础设施得到了显著改进,并提供了基于注释的模型以及发布任意事件的能力(也就是说,不一定是从ApplicationEvent扩展的对象)。当这样的对象被发布时,我们将它包装在一个事件中。JM728资讯网——每日最新资讯28at.com

JM728资讯网——每日最新资讯28at.com

以下是一个简单的事件应用JM728资讯网——每日最新资讯28at.com

1.1 定义事件对象

public class PackEvent extends ApplicationEvent {  private static final long serialVersionUID = 1L;  public PackEvent(Object source) {    super(source);  }}

1.2 定义事件监听

@Componentpublic class PackEventListener implements ApplicationListener<PackEvent> {  @Override  public void onApplicationEvent(PackEvent event) {    System.out.println("触发事件...") ;  }}

1.3 发布事件

@Resourceprivate ApplicationEventMulticaster eventMulticaster ;public void run(ApplicationArguments args) throws Exception {  eventMulticaster.multicastEvent(new PackEvent("自定义Pack")) ;}

以上Spring事件系统的完整应用实例。在默认情况下该种事件处理方式是同步的,也就是事件的发布者与事件的处理都是同一个线程中,那这就要求我们的事件处理程序不应该处理复杂耗时的任务,否则会影响我们的主业务系统。那如何异步处理事件呢?JM728资讯网——每日最新资讯28at.com

2. 事件异步处理

2.1 通过@Async注解

该种方式是最简单的方式了,开启异步功能,在基于注解的事件监听方法上使用@Async注解。JM728资讯网——每日最新资讯28at.com

开启异步任务功能更JM728资讯网——每日最新资讯28at.com

@EnableAsyncpublic class AppApplication {}

基于注解事件监听JM728资讯网——每日最新资讯28at.com

@Async@EventListener({PackEvent.class})public void packEventListener(PackEvent event) {  System.out.printf("%s - 事件发生了...%s%n", Thread.currentThread().getName(), event.getSource()) ;}

执行结果JM728资讯网——每日最新资讯28at.com

task-1 - 事件发生了...自定义Pack

线程名已经变为了task-1。task-前缀是异步线程的默认名。关于异步任务执行应用的线程池配置,查看下面这篇文章。JM728资讯网——每日最新资讯28at.com

Spring任务调度&异步任务&Web异步请求三者如何配置线程池?JM728资讯网——每日最新资讯28at.com

上面是基于注解的方式应用异步执行事件处理。对于在简介中通过实现ApplicationListener接口的方式又该如何处理呢?JM728资讯网——每日最新资讯28at.com

对于这种方式,我们可以通过两种方式进行处理:JM728资讯网——每日最新资讯28at.com

2.2 自定义线程池

  • 在事件监听处理程序中开启异步线程
@Componentpublic class PackEventListener implements ApplicationListener<PackEvent> {  @Override  public void onApplicationEvent(PackEvent event) {    new Thread(() -> {      System.out.printf("%s触发事件...%n", Thread.currentThread().getName()) ;    }).start() ;  }}
  • 自定义事件广播器
@BeanTaskExecutor taskExecutor() {  ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor() ;  taskExecutor.setThreadNamePrefix("pack-event-") ;  taskExecutor.setCorePoolSize(5) ;  taskExecutor.setQueueCapacity(100) ;  taskExecutor.setMaxPoolSize(5) ;  taskExecutor.initialize() ;  return taskExecutor ;}// 注意beanName必须为applicationEventMulticaster;下面的源码中你将看到@Bean(name  = AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)SimpleApplicationEventMulticaster eventMulticaster(BeanFactory beanFactory) {  SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster(beanFactory) ;  eventMulticaster.setTaskExecutor(taskExecutor()) ;  return eventMulticaster ;}

通过这种方式也可以实现事件处理程序异步执行。而这种方式的实现原理如下:JM728资讯网——每日最新资讯28at.com

容器启动中的核心方法refresh中JM728资讯网——每日最新资讯28at.com

public abstract class AbstractApplicationContext {  public void refresh() {    // 初始化事件广播器    initApplicationEventMulticaster();  }  protected void initApplicationEventMulticaster() {    ConfigurableListableBeanFactory beanFactory = getBeanFactory();    // 判断容器中是否存在beanName=applicationEventMulticaster    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {      this.applicationEventMulticaster =          beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);    } else {      // 如果不存在则创建一个同步的执行器。      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);    }  }}

以上是本篇文章的全部内容,希望对你有帮助。JM728资讯网——每日最新资讯28at.com

完毕!!!JM728资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-76561-0.htmlSpring事件如何异步执行?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Spring中Cron表达式的优雅实现方案

下一篇: OpenFeign夺命连环九问

标签:
  • 热门焦点
  • 中兴AX5400Pro+上手体验:再升级 双2.5G网口+USB 3.0这次全都有

    中兴AX5400Pro+上手体验:再升级 双2.5G网口+USB 3.0这次全都有

    2021年11月的时候,中兴先后发布了两款路由器产品,中兴AX5400和中兴AX5400 Pro,从产品命名上就不难看出这是隶属于同一系列的,但在外观设计上这两款产品可以说是完全没一点关系
  • 从 Pulsar Client 的原理到它的监控面板

    从 Pulsar Client 的原理到它的监控面板

    背景前段时间业务团队偶尔会碰到一些 Pulsar 使用的问题,比如消息阻塞不消费了、生产者消息发送缓慢等各种问题。虽然我们有个监控页面可以根据 topic 维度查看他的发送状态,
  • 分布式系统中的CAP理论,面试必问,你理解了嘛?

    分布式系统中的CAP理论,面试必问,你理解了嘛?

    对于刚刚接触分布式系统的小伙伴们来说,一提起分布式系统,就感觉高大上,深不可测。而且看了很多书和视频还是一脸懵逼。这篇文章主要使用大白话的方式,带你理解一下分布式系统
  • 如何使用JavaScript创建一只图像放大镜?

    如何使用JavaScript创建一只图像放大镜?

    译者 | 布加迪审校 | 重楼如果您曾经浏览过购物网站,可能遇到过图像放大功能。它可以让您放大图像的特定区域,以便浏览。结合这个小小的重要功能可以大大改善您网站的用户体验
  • 一篇文章带你了解 CSS 属性选择器

    一篇文章带你了解 CSS 属性选择器

    属性选择器对带有指定属性的 HTML 元素设置样式。可以为拥有指定属性的 HTML 元素设置样式,而不仅限于 class 和 id 属性。一、了解属性选择器CSS属性选择器提供了一种简单而
  • 电视息屏休眠仍有网络上传 爱奇艺被质疑“薅消费者羊毛”

    电视息屏休眠仍有网络上传 爱奇艺被质疑“薅消费者羊毛”

    记者丨宁晓敏 见习生丨汗青出品丨鳌头财经(theSankei) 前不久,爱奇艺发布了一份亮眼的一季报,不仅营收和会员营收创造历史最佳表现,其运营利润也连续6个月实现增长。自去年年初
  • 自律,给不了Keep自由!

    自律,给不了Keep自由!

    来源 | 互联网品牌官作者 | 李大为编排 | 又耳 审核 | 谷晓辉自律能不能给用户自由暂时不好说,但大概率不能给Keep自由。近日,全球最大的在线健身平台Keep正式登陆港交所,努力
  • 腾讯VS网易,最卷游戏暑期档,谁能笑到最后?

    腾讯VS网易,最卷游戏暑期档,谁能笑到最后?

    作者:无锈钵来源:财经无忌7月16日晚,上海1862时尚艺术中心。伴随着幻象的精准命中,硕大的荧幕之上,比分被定格在了14:12,被寄予厚望的EDG战队以绝对的优势战胜了BLG战队,拿下了总决
  • 质感不错!OPPO K11渲染图曝光:旗舰IMX890传感器首次下放

    质感不错!OPPO K11渲染图曝光:旗舰IMX890传感器首次下放

    一直以来,OPPO K系列机型都保持着较为均衡的产品体验,历来都是2K价位的明星机型,去年推出的OPPO K10和OPPO K10 Pro两款机型凭借各自的出色配置,堪称有
Top
Baidu
map