日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring5源码 - 12 Spring事件监听机制_异步事件监听应用及源码解析

發布時間:2025/3/21 javascript 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring5源码 - 12 Spring事件监听机制_异步事件监听应用及源码解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • Pre
  • 實現原理
  • 應用
    • 配置類
    • Event事件
    • 事件監聽 EventListener
    • 發布事件 publishEvent
  • 源碼解析 (反推)
    • Spring默認的事件廣播器 SimpleApplicationEventMulticaster#multicastEvent
    • 獲取executor
    • 設置executor
    • 得出操作步驟
      • 方式一
      • 方式二
  • 其他開啟異步的方式


Pre

Spring5源碼 - 11 Spring事件監聽機制_源碼篇


實現原理

Spring提供的事件機制,默認是同步的。如果想要使用異步事件監聽,可以自己實現ApplicationEventMulticaster接口,并在Spring容器中注冊id為applicationEventMulticaster的Bean , 設置 executor 。

Spring會遍歷所有的ApplicationListener, 如果 taskExecutor 不為空,這開啟異步線程執行。


應用

配置類

package com.artisan.eventlistener2;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.ApplicationEventMulticaster; import org.springframework.context.event.SimpleApplicationEventMulticaster; import org.springframework.core.task.SimpleAsyncTaskExecutor;@Configuration @ComponentScan("com.artisan.eventlistener2") public class ArtisanConfig {@Bean(name = "applicationEventMulticaster") // Step1: id必須叫 applicationEventMulticasterpublic ApplicationEventMulticaster multicaster(){// Step2:實例化SimpleApplicationEventMulticaster SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();// Step3:設置TaskExecutor simpleApplicationEventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());return simpleApplicationEventMulticaster ;}}

Event事件

package com.artisan.eventlistener2;import org.springframework.context.ApplicationEvent;public class ArtisanEvent extends ApplicationEvent {private String msg ;public ArtisanEvent(Object source) {super(source);}public ArtisanEvent(Object source,String msg) {super(source);this.msg = msg ;}public void print(){System.out.println(Thread.currentThread().getName() + "-----" + msg);}}

事件監聽 EventListener

package com.artisan.eventlistener2;import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component;@Component public class ArtisanListenerByAnno {@EventListener(ArtisanEvent.class)public void onApplicationEvent(ArtisanEvent event) {System.out.println(Thread.currentThread().getName() + " EventListener 監聽到ArtisanEvent.....");event.print();} }

發布事件 publishEvent

package com.artisan.eventlistener2;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class ArtisanTest {public static void main(String[] args) {AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ArtisanConfig.class);// 模擬發布事件ac.publishEvent(new ArtisanEvent("xxxx","msg from artisanEvent"));System.out.println(Thread.currentThread().getName() + " over");} }

【結果】

如果我們把配置類中的

@Bean(name = "applicationEventMulticaster")public ApplicationEventMulticaster multicaster(){SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();simpleApplicationEventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());return simpleApplicationEventMulticaster ;}

移除掉,重新運行

就變成了默認的同步監聽了。。。。


源碼解析 (反推)

Spring默認的事件廣播器 SimpleApplicationEventMulticaster#multicastEvent

我們分析一下 ac.publishEvent(new ArtisanEvent("xxxx","msg from artisanEvent")); 最終會調用到

org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)


獲取executor

executor不為null則異步處理, 那看下executor = getTaskExecutor();

SimpleApplicationEventMulticaster的一個屬性

那只要在實例化SimpleApplicationEventMulticaster的時候 set屬性值就可以了哇。

所以現在的問題是什么時候給線程池屬性賦值的問題?


設置executor

我們知道

org.springframework.context.support.AbstractApplicationContext#refresh

看看 initApplicationEventMulticaster

protected void initApplicationEventMulticaster() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();//判斷IOC容器中包含applicationEventMulticaster 事件多播器的Bean的nameif (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {//創建一個applicationEventMulticaster的bean放在IOC 容器中,bean的name 為applicationEventMulticasterthis.applicationEventMulticaster =beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);if (logger.isDebugEnabled()) {logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");}}else { //容器中不包含一個beanName 為applicationEventMulticaster的多播器組件//創建一個SimpleApplicationEventMulticaster 多播器this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);//注冊到容器中beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);if (logger.isDebugEnabled()) {logger.debug("Unable to locate ApplicationEventMulticaster with name '" +APPLICATION_EVENT_MULTICASTER_BEAN_NAME +"': using default [" + this.applicationEventMulticaster + "]");}}}

通過源碼我們知道,Spring會先從容器中找 bean name 為 “applicationEventMulticaster” 的 bean,so問題就簡單了,我們只要自定義個 bean name 為 applicationEventMulticaster 的 bean,并給其屬性 taskExecutor 賦上自定義的線程池即可,這個時候就能實現異步事件處理了 .

得出操作步驟

所以,可以這么配置

方式一

@Configuration @ComponentScan("com.artisan.eventlistener2") public class ArtisanConfig {@Bean(name = "applicationEventMulticaster")public ApplicationEventMulticaster multicaster(){SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();simpleApplicationEventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());return simpleApplicationEventMulticaster ;}}

方式二

或者寫一個類實現 AbstractApplicationEventMulticaster ,仿照 SimpleApplicationEventMulticaster 即可

package com.artisan.eventlistener2;import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.AbstractApplicationEventMulticaster; import org.springframework.core.ResolvableType; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.core.task.TaskExecutor; import org.springframework.stereotype.Component;import java.util.Iterator;@Component("applicationEventMulticaster") public class AsyncApplicationEventMulticaster extends AbstractApplicationEventMulticaster {private TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();public void setTaskExecutor(TaskExecutor taskExecutor) {this.taskExecutor = (taskExecutor != null ? taskExecutor : new SimpleAsyncTaskExecutor());}protected TaskExecutor getTaskExecutor() {return this.taskExecutor;}@Override@SuppressWarnings("unchecked")public void multicastEvent(final ApplicationEvent event) {}@Overridepublic void multicastEvent(ApplicationEvent event, ResolvableType eventType) {for (Iterator<ApplicationListener<?>> it = getApplicationListeners().iterator(); it.hasNext();) {final ApplicationListener listener = it.next();System.out.println("-----------自定義異步事件監聽-----------");getTaskExecutor().execute(() -> listener.onApplicationEvent(event));}} }


其他開啟異步的方式

@EnbaleAsyn + @Async

總結

以上是生活随笔為你收集整理的Spring5源码 - 12 Spring事件监听机制_异步事件监听应用及源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。