自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring事件如何異步執(zhí)行?

開發(fā) 前端
從Spring 4.2開始,事件基礎(chǔ)設(shè)施得到了顯著改進(jìn),并提供了基于注釋的模型以及發(fā)布任意事件的能力(也就是說,不一定是從ApplicationEvent擴(kuò)展的對象)。當(dāng)這樣的對象被發(fā)布時(shí),我們將它包裝在一個(gè)事件中。

環(huán)境:SpringBoot2.7.16

1. 簡介

ApplicationContext 中的事件處理是通過 ApplicationEvent 類和 ApplicationListener 接口提供的。如果在上下文中部署了實(shí)現(xiàn) ApplicationListener 接口的 Bean,那么每次 ApplicationEvent 發(fā)布到 ApplicationContext 時(shí),都會(huì)通知該 Bean。從本質(zhì)上講,這就是標(biāo)準(zhǔn)的觀察者設(shè)計(jì)模式。

從Spring 4.2開始,事件基礎(chǔ)設(shè)施得到了顯著改進(jìn),并提供了基于注釋的模型以及發(fā)布任意事件的能力(也就是說,不一定是從ApplicationEvent擴(kuò)展的對象)。當(dāng)這樣的對象被發(fā)布時(shí),我們將它包裝在一個(gè)事件中。

以下是一個(gè)簡單的事件應(yīng)用

1.1 定義事件對象

public class PackEvent extends ApplicationEvent {


  private static final long serialVersionUID = 1L;


  public PackEvent(Object source) {
    super(source);
  }
}

1.2 定義事件監(jiān)聽

@Component
public class PackEventListener implements ApplicationListener<PackEvent> {


  @Override
  public void onApplicationEvent(PackEvent event) {
    System.out.println("觸發(fā)事件...") ;
  }
}

1.3 發(fā)布事件

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

以上Spring事件系統(tǒng)的完整應(yīng)用實(shí)例。在默認(rèn)情況下該種事件處理方式是同步的,也就是事件的發(fā)布者與事件的處理都是同一個(gè)線程中,那這就要求我們的事件處理程序不應(yīng)該處理復(fù)雜耗時(shí)的任務(wù),否則會(huì)影響我們的主業(yè)務(wù)系統(tǒng)。那如何異步處理事件呢?

2. 事件異步處理

2.1 通過@Async注解

該種方式是最簡單的方式了,開啟異步功能,在基于注解的事件監(jiān)聽方法上使用@Async注解。

開啟異步任務(wù)功能更

@EnableAsync
public class AppApplication {}

基于注解事件監(jiān)聽

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

執(zhí)行結(jié)果

task-1 - 事件發(fā)生了...自定義Pack

線程名已經(jīng)變?yōu)榱藅ask-1。task-前綴是異步線程的默認(rèn)名。關(guān)于異步任務(wù)執(zhí)行應(yīng)用的線程池配置,查看下面這篇文章。

Spring任務(wù)調(diào)度&異步任務(wù)&Web異步請求三者如何配置線程池?

上面是基于注解的方式應(yīng)用異步執(zhí)行事件處理。對于在簡介中通過實(shí)現(xiàn)ApplicationListener接口的方式又該如何處理呢?

對于這種方式,我們可以通過兩種方式進(jìn)行處理:

2.2 自定義線程池

  • 在事件監(jiān)聽處理程序中開啟異步線程
@Component
public class PackEventListener implements ApplicationListener<PackEvent> {


  @Override
  public void onApplicationEvent(PackEvent event) {
    new Thread(() -> {
      System.out.printf("%s觸發(fā)事件...%n", Thread.currentThread().getName()) ;
    }).start() ;
  }
}
  • 自定義事件廣播器
@Bean
TaskExecutor 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 ;
}

通過這種方式也可以實(shí)現(xiàn)事件處理程序異步執(zhí)行。而這種方式的實(shí)現(xiàn)原理如下:

容器啟動(dòng)中的核心方法refresh中

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 {
      // 如果不存在則創(chuàng)建一個(gè)同步的執(zhí)行器。
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    }
  }
}

以上是本篇文章的全部內(nèi)容,希望對你有幫助。

完畢?。?!

責(zé)任編輯:武曉燕 來源: Spring全家桶實(shí)戰(zhàn)案例源碼
相關(guān)推薦

2013-04-01 15:25:41

異步編程異步EMP

2022-02-11 08:54:33

SpringWeb 應(yīng)用執(zhí)行表單

2023-07-31 08:05:30

Spring任務(wù)調(diào)度

2020-07-02 07:44:27

Spring教程異步

2025-02-07 10:14:36

2023-02-07 07:25:36

Spring事件驅(qū)動(dòng)

2010-08-04 13:23:29

Flex事件

2015-09-07 14:08:32

Java編程異步事件

2013-03-08 09:33:25

JavaScript同步異步

2009-07-22 10:13:31

異步ActionASP.NET MVC

2020-11-01 17:10:46

異步事件開發(fā)前端

2024-07-31 15:57:41

2024-10-15 10:28:43

2021-06-26 14:59:13

SpringTransaction執(zhí)行

2021-05-31 07:30:47

Connectsocket函數(shù)

2010-04-06 15:20:56

ASP.NET MVC

2024-01-08 08:45:07

Spring容器Bean

2020-01-02 16:30:02

Spring BootJava異步請求

2024-12-17 00:00:00

Spring線程

2023-02-26 10:59:51

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)