Spring 自定義事件監(jiān)聽器實(shí)現(xiàn)步驟詳解
Spring 自定義事件監(jiān)聽器的實(shí)現(xiàn)核心遵循「定義事件 → 發(fā)布事件 → 監(jiān)聽并處理事件」的核心流程,可結(jié)合異步、自定義線程池等擴(kuò)展能力,以下是標(biāo)準(zhǔn)化步驟(附核心代碼和關(guān)鍵說明):
步驟 1:基礎(chǔ)準(zhǔn)備(可選,默認(rèn)已支持)
Spring Boot 項(xiàng)目中默認(rèn)內(nèi)置事件驅(qū)動能力,無需額外依賴;若需異步執(zhí)行監(jiān)聽器,需在主類 / 配置類上添加 @EnableAsync 注解開啟異步支持:
@SpringBootApplication
@EnableAsync // 僅異步場景需要
public class EcommerceApplication {
public static void main(String[] args) {
SpringApplication.run(EcommerceApplication.class, args);
}
}步驟 2:定義自定義事件類
創(chuàng)建事件類,繼承 Spring 提供的 ApplicationEvent(或 PayloadApplicationEvent,簡化版),封裝事件需要傳遞的業(yè)務(wù)數(shù)據(jù)(如訂單信息、用戶信息):
核心規(guī)則:
- 必須通過構(gòu)造函數(shù)傳遞
source(事件源,通常是發(fā)布事件的對象); - 按需添加業(yè)務(wù)屬性(如訂單、用戶 ID)和 getter 方法。
代碼示例(電商下單事件):
// 自定義事件類
public class OrderPlacedEvent extends ApplicationEvent {
// 事件攜帶的業(yè)務(wù)數(shù)據(jù)
private final Order order;
// 構(gòu)造函數(shù):source=事件源(如OrderService),order=業(yè)務(wù)數(shù)據(jù)
public OrderPlacedEvent(Object source, Order order) {
super(source);
this.order = order;
}
// 獲取業(yè)務(wù)數(shù)據(jù)的getter
public Order getOrder() {
return order;
}
}
// 配套的業(yè)務(wù)模型(示例)
public class Order {
private String orderId;
private String userId;
private double amount;
// 省略構(gòu)造器、getter/setter
}步驟 3:實(shí)現(xiàn)事件發(fā)布者(觸發(fā)事件)
在業(yè)務(wù)邏輯組件(如 Service)中,注入 ApplicationEventPublisher(Spring 自動提供),在需要觸發(fā)事件的時(shí)機(jī)(如訂單創(chuàng)建成功后)調(diào)用 publishEvent() 發(fā)布自定義事件:
核心規(guī)則:
- 事件發(fā)布時(shí)機(jī)完全自定義(如業(yè)務(wù)邏輯成功后、特定條件滿足時(shí));
ApplicationEventPublisher可直接注入,無需手動實(shí)例化。
代碼示例:
@Service
public class OrderService {
// 注入事件發(fā)布器
@Autowired
private ApplicationEventPublisher eventPublisher;
// 核心業(yè)務(wù)方法:創(chuàng)建訂單后發(fā)布事件
public void placeOrder(Order order) {
// 1. 執(zhí)行核心業(yè)務(wù)邏輯(如保存訂單到數(shù)據(jù)庫)
order.setOrderId("ORDER-" + System.currentTimeMillis());
System.out.println("訂單創(chuàng)建成功:" + order.getOrderId());
// 2. 發(fā)布自定義事件(觸發(fā)時(shí)機(jī)由業(yè)務(wù)決定)
eventPublisher.publishEvent(new OrderPlacedEvent(this, order));
}
}步驟 4:實(shí)現(xiàn)事件監(jiān)聽器(處理事件)
創(chuàng)建監(jiān)聽器組件(標(biāo)注 @Component 讓 Spring 掃描),通過以下兩種方式綁定并處理自定義事件:
方式 1:@EventListener 注解(推薦,簡潔)
通過方法參數(shù)類型隱式綁定事件(最常用),或通過注解 classes 屬性顯式綁定,支持異步(添加 @Async):
@Component
public class InventoryListener {
// 方式1:參數(shù)類型隱式綁定OrderPlacedEvent
@Async // 可選:異步執(zhí)行,需配合@EnableAsync
@EventListener
public void handleOrderEvent(OrderPlacedEvent event) {
Order order = event.getOrder();
// 處理事件邏輯(如扣減庫存)
System.out.println("【庫存監(jiān)聽器】處理訂單:" + order.getOrderId() + ",扣減庫存");
}
}
// 方式2:顯式指定監(jiān)聽的事件類型(支持多事件)
@Component
public class NotificationListener {
@EventListener(classes = {OrderPlacedEvent.class})
public void handleMultiEvent(Object event) {
if (event instanceof OrderPlacedEvent) {
Order order = ((OrderPlacedEvent) event).getOrder();
// 處理事件邏輯(如發(fā)送通知)
System.out.println("【通知監(jiān)聽器】處理訂單:" + order.getOrderId() + ",發(fā)送下單通知");
}
}
}方式 2:實(shí)現(xiàn) ApplicationListener 接口(傳統(tǒng)方式)
直接實(shí)現(xiàn)接口,泛型指定要監(jiān)聽的事件類型:
@Component
public class AnalyticsListener implements ApplicationListener<OrderPlacedEvent> {
@Override
public void onApplicationEvent(OrderPlacedEvent event) {
Order order = event.getOrder();
// 處理事件邏輯(如統(tǒng)計(jì)銷售數(shù)據(jù))
System.out.println("【分析監(jiān)聽器】處理訂單:" + order.getOrderId() + ",統(tǒng)計(jì)銷售數(shù)據(jù)");
}
}步驟 5(可選):自定義異步線程池(生產(chǎn)環(huán)境推薦)
默認(rèn)異步線程池為臨時(shí)創(chuàng)建線程,生產(chǎn)環(huán)境建議自定義線程池控制資源:
@Configuration
public class AsyncConfig {
@Bean(name = "asyncTaskExecutor")
public Executor asyncTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 核心線程數(shù)
executor.setMaxPoolSize(10); // 最大線程數(shù)
executor.setQueueCapacity(20); // 任務(wù)隊(duì)列
executor.setThreadNamePrefix("Async-"); // 線程名前綴
executor.initialize();
return executor;
}
}
// 監(jiān)聽器指定自定義線程池
@Async("asyncTaskExecutor")
@EventListener
public void handleOrderEvent(OrderPlacedEvent event) {
// 業(yè)務(wù)邏輯...
}步驟 6:測試驗(yàn)證
通過 Controller / 測試類觸發(fā)業(yè)務(wù)邏輯,驗(yàn)證事件發(fā)布和監(jiān)聽是否生效:
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping
public String createOrder(@RequestBody Order order) {
orderService.placeOrder(order);
return "訂單提交成功,訂單號:" + order.getOrderId();
}
}核心總結(jié)
| 步驟 | 核心操作 | 關(guān)鍵注解 / 類 |
|---|---|---|
| 1 | 基礎(chǔ)準(zhǔn)備 | @EnableAsync(異步場景) |
| 2 | 定義事件 | ApplicationEvent(父類) |
| 3 | 發(fā)布事件 | ApplicationEventPublisher + publishEvent() |
| 4 | 監(jiān)聽事件 | @EventListener / ApplicationListener |
| 5 | 異步優(yōu)化 | 自定義 ThreadPoolTaskExecutor + @Async("線程池名") |
核心優(yōu)勢:
- 解耦:發(fā)布者無需關(guān)心監(jiān)聽器邏輯,新增 / 移除監(jiān)聽器不修改核心業(yè)務(wù)代碼;
- 靈活:支持同步 / 異步執(zhí)行,可多監(jiān)聽器并發(fā)處理同一事件;
- 可擴(kuò)展:事件攜帶業(yè)務(wù)數(shù)據(jù),監(jiān)聽器職責(zé)單一,便于維護(hù)。
到此這篇關(guān)于Spring 自定義事件監(jiān)聽器實(shí)現(xiàn)步驟的文章就介紹到這了,更多相關(guān)Spring事件監(jiān)聽器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于spring依賴注入的方式以及優(yōu)缺點(diǎn)
這篇文章主要介紹了關(guān)于spring依賴注入的方式以及優(yōu)缺點(diǎn),依賴注入,是IOC的一個方面,是個通常的概念,它有多種解釋,這概念是說你不用創(chuàng)建對象,而只需要描述它如何被創(chuàng)建,需要的朋友可以參考下2023-07-07
用Rational Rose逆向工程(java)生成類圖(教程和錯誤解決)
Rational Rose有個很方便的功能,將項(xiàng)目中的JAVA代碼自動轉(zhuǎn)換成UML類圖2013-02-02
Spring AOP + 注解實(shí)現(xiàn)統(tǒng)一注解功能
本文我們通過Spring AOP和Java的自定義注解來實(shí)現(xiàn)日志的插入功能,非常不錯,具有一定的參考借鑒價(jià)值,需要的朋友一起看看吧2018-05-05
IDEA 2021.2 激活教程及啟動報(bào)錯問題解決方法
這篇文章主要介紹了IDEA 2021.2 啟動報(bào)錯及激活教程,文章開頭給大家介紹了idea2021最新激活方法,關(guān)于idea2021啟動報(bào)錯的問題小編也給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-10-10
SpringBoot解決BigDecimal傳到前端后精度丟失問題
這篇文章將通過示例詳細(xì)為大家介紹SpringBoot如何解決BigDecimal傳到前端后精度丟失問題,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-06-06
Nacos通過RefreshScope實(shí)現(xiàn)配置自動更新的方式分享
這篇文章主要給大家介紹了Nacos如何通過RefreshScope實(shí)現(xiàn)配置自動更新,文中給了兩種實(shí)現(xiàn)方式供大家參考,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-09-09

