Spring中事件機(jī)制的實(shí)現(xiàn)示例
Spring中的事件機(jī)制是基于觀察者模式實(shí)現(xiàn)的一種組件間通信機(jī)制,用于解耦不同組件,實(shí)現(xiàn)松耦合的消息傳遞,它允許一個(gè)組件發(fā)送事件,其他組件接收并處理事件,而無(wú)需直接依賴彼此。
事件機(jī)制的組成
Spring事件機(jī)制包含三個(gè)核心部分:
- 事件:繼承ApplicationEvent的對(duì)象,封裝需要傳遞的數(shù)據(jù)。Spring4.2+可以省略,任意對(duì)象都可以作為事件。
- 事件發(fā)布者:通過(guò)ApplicationEventPublisher接口發(fā)布事件,通常由spring管理的bean實(shí)現(xiàn)。
- 事件監(jiān)聽器:監(jiān)聽并處理事件的組件,通過(guò)@EventListener注解或?qū)崿F(xiàn)ApplicationListener接口定義。
示例
事件:
首先自定義一個(gè)事件類,去實(shí)現(xiàn)ApplicationEvent,該父類沒有無(wú)參構(gòu)造:
public class MyEvent extends ApplicationEvent {
public MyEvent(Object source) {
super(source);
}
}
發(fā)布者:
在業(yè)務(wù)代碼內(nèi)注入ApplicationEventPublisher,通過(guò)它去發(fā)布事件:
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
public void enent(){
//業(yè)務(wù)代碼
//發(fā)送事件
applicationEventPublisher.publishEvent(new MyEvent(this));
}監(jiān)聽器:
監(jiān)聽事件類型,兩種方式都試一遍:
@Component
public class MyLin implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("監(jiān)聽到事件");
}
}@Component
public class MyLin2 {
//注意方法的參數(shù)類型是監(jiān)聽的類型
@EventListener
public void onApplicationEvent(MyEvent event) {
System.out.println("監(jiān)聽到事件2");
}
}

接下來(lái)模擬異步的情況:
SimpleApplicationEventMulticaster
SimpleApplicationEventMulticaster是 Spring 框架中事件機(jī)制的核心組件,負(fù)責(zé)將發(fā)布的事件多播(multicast) 給所有訂閱該事件的監(jiān)聽器,是事件從發(fā)布者傳遞到監(jiān)聽器的 “中介”。
它的主要職責(zé)是:
- 接收發(fā)布者發(fā)布的事件;
- 找到所有監(jiān)聽該事件類型的監(jiān)聽器;
- 將事件分發(fā)給這些監(jiān)聽器執(zhí)行處理邏輯。
特性:
- 事件發(fā)布后,它會(huì)直接發(fā)布在事件的線程中調(diào)研監(jiān)聽器的處理方法,發(fā)布者需等待所有的監(jiān)聽器完畢后才能繼續(xù),可以過(guò)setTaskExector(Executor)設(shè)置線程池,會(huì)將監(jiān)聽器的處理邏輯交到線程池執(zhí)行,發(fā)布者無(wú)需等待。
- 支持通過(guò)
addApplicationListener(ApplicationListener)手動(dòng)注冊(cè)監(jiān)聽器;
配置好SimpleApplicationEventMulticaster后,通過(guò)ApplicationEventPublish發(fā)送事件后會(huì)提交到配置的線程池中執(zhí)行。
@Bean
public SimpleApplicationEventMulticaster applicationEventMulticaster(ThreadPoolExecutor executor){
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
multicaster.setTaskExecutor(executor);
return multicaster;
}
異步事件監(jiān)聽器
@Component
public class AsyncEventListener {
private static final Logger logger = LoggerFactory.getLogger(AsyncEventListener.class);
/**
* 異步處理事件 - 不會(huì)阻塞主線程
*/
@Async("taskExecutor") // 指定使用配置的線程池
@EventListener
public void handleAsyncEvent(MyEvent event) {
logger.info("異步事件處理開始 - 事件: {}", event.getMessage());
logger.info("當(dāng)前線程: {}", Thread.currentThread().getName());
try {
// 模擬耗時(shí)操作
Thread.sleep(3000);
logger.info("異步事件處理完成: {}", event.getMessage());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("異步事件處理被中斷", e);
}
}
/**
* 同步處理事件 - 會(huì)阻塞主線程
*/
@EventListener
public void handleSyncEvent(MyEvent event) {
logger.info("同步事件處理開始 - 事件: {}", event.getMessage());
logger.info("當(dāng)前線程: {}", Thread.currentThread().getName());
try {
// 模擬耗時(shí)操作
Thread.sleep(2000);
logger.info("同步事件處理完成: {}", event.getMessage());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("同步事件處理被中斷", e);
}
}
}@SpringBootTest
public class EventTest {
@Autowired
private BusinessService businessService;
@Test
public void testAsyncEvent() {
System.out.println("測(cè)試開始 - 主線程: " + Thread.currentThread().getName());
long startTime = System.currentTimeMillis();
businessService.doBusiness();
long endTime = System.currentTimeMillis();
System.out.println("業(yè)務(wù)方法執(zhí)行時(shí)間: " + (endTime - startTime) + "ms");
// 給異步事件處理留出時(shí)間
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}Spring 內(nèi)置事件
Spring 框架自帶一些內(nèi)置事件,用于通知容器生命周期的關(guān)鍵節(jié)點(diǎn),常見的有:
| 事件類型 | 觸發(fā)時(shí)機(jī) |
|---|---|
| ContextRefreshedEvent | Spring 容器初始化完成(所有 Bean 加載完成) |
| ContextStartedEvent | 容器啟動(dòng)時(shí)(調(diào)用start()方法) |
| ContextStoppedEvent | 容器停止時(shí)(調(diào)用stop()方法) |
| ContextClosedEvent | 容器關(guān)閉時(shí)(調(diào)用close()方法) |
| ApplicationFailedEvent | 應(yīng)用啟動(dòng)失敗時(shí)(Spring Boot 中常用) |
到此這篇關(guān)于Spring中事件機(jī)制的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Spring 事件機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java ssm框架實(shí)現(xiàn)分頁(yè)功能的示例代碼(oracle)
這篇文章主要介紹了java ssm框架實(shí)現(xiàn)分頁(yè)功能的示例代碼(oracle),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
java Struts2框架下實(shí)現(xiàn)文件上傳功能
這篇文章主要為大家詳細(xì)介紹了java Struts2框架下實(shí)現(xiàn)文件上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
Java實(shí)現(xiàn)簡(jiǎn)易俄羅斯方塊
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)易俄羅斯方塊,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06

