首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring 事件機制進階:SmartApplicationListener 實現多監聽器有序流水線處理 (審核流程實戰)

     編輯:Java 綜合教學

Spring 事件機制進階:SmartApplicationListener 實現多監聽器有序流水線處理 (審核流程實戰)

場景痛點

標準 ApplicationListener 無序、異步執行,無法滿足「嚴格順序、上一步通過才執行下一步、同步阻塞」的業務流程(如多級審核、流水線任務)。

解決方案:SmartApplicationListener + getOrder()

SmartApplicationListener 繼承 ApplicationListener,新增三大能力:

  • getOrder():定義執行優先級(值越小越先執行)。
  • supportsEventType():聲明關心的事件類型,避免無關事件干擾。
  • supportsSourceType():聲明關心的事件源類型,精準過濾。

實戰案例:三級創新獎項審核流水線

1. 事件對象

public class AuditEvent extends ApplicationEvent {
    private Boolean status = true;      // 當前審核狀態
    private String work;                // 申報作品
    private String advice = "待審核";    // 審核意見

    public AuditEvent(Object source, String work) {
        super(source);
        this.work = work;
    }
    // getter/setter 略
}

2. 事件發布者 (學生小白)

public class XiaoBai implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    public void reportWork(String work) {
        AuditEvent event = new AuditEvent(this, work);
        applicationContext.publishEvent(event); // 同步發布,阻塞直到所有監聽器完成
        System.out.println("最終結果: " + event.getStatus() + " -- " + event.getAdvice());
    }

    @Override public void setApplicationContext(ApplicationContext ctx) { this.applicationContext = ctx; }
}

3. 三級監聽器 (核心:實現 SmartApplicationListener)

// 學校級審核 (Order=1)
public class SchoolListener implements SmartApplicationListener {
    @Override public void onApplicationEvent(ApplicationEvent event) {
        AuditEvent e = (AuditEvent) event;
        System.out.println("[學校] 狀態:" + e.getStatus() + " 意見:" + e.getAdvice());
        e.setStatus(true);
        e.setAdvice("學校: 有創意,通過!");
    }
    @Override public int getOrder() { return 1; }
    @Override public boolean supportsEventType(Class t) { return AuditEvent.class == t; }
    @Override public boolean supportsSourceType(Class t) { return XiaoBai.class == t; }
}

// 省級審核 (Order=2)
public class ProvinceListener implements SmartApplicationListener {
    @Override public void onApplicationEvent(ApplicationEvent event) {
        AuditEvent e = (AuditEvent) event;
        if (!e.getStatus()) return; // 上級駁回則跳過
        System.out.println("[省級] 狀態:" + e.getStatus() + " 意見:" + e.getAdvice());
        e.setStatus(true);
        e.setAdvice("省級: 還行,通過!");
    }
    @Override public int getOrder() { return 2; }
    @Override public boolean supportsEventType(Class t) { return AuditEvent.class == t; }
    @Override public boolean supportsSourceType(Class t) { return XiaoBai.class == t; }
}

// 國家級審核 (Order=3)
public class CountryListener implements SmartApplicationListener {
    @Override public void onApplicationEvent(ApplicationEvent event) {
        AuditEvent e = (AuditEvent) event;
        if (!e.getStatus()) return;
        System.out.println("[國家] 狀態:" + e.getStatus() + " 意見:" + e.getAdvice());
        e.setStatus(true);
        e.setAdvice("國家: 勉強通過!");
    }
    @Override public int getOrder() { return 3; }
    @Override public boolean supportsEventType(Class t) { return AuditEvent.class == t; }
    @Override public boolean supportsSourceType(Class t) { return XiaoBai.class == t; }
}

4. Spring XML 注冊

<bean id="schoolListener" class="com.example.event.SchoolListener"/>
<bean id="provinceListener" class="com.example.event.ProvinceListener"/>
<bean id="countryListener" class="com.example.event.CountryListener"/>
<bean id="xiaoBai" class="com.example.event.XiaoBai"/>

5. 測試驗證

public class MainTest {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("event-flow.xml");
        XiaoBai xb = ctx.getBean(XiaoBai.class);
        xb.reportWork("智能機器人");
    }
}

6. 輸出結果

[學校] 狀態:true 意見:待審核
[省級] 狀態:true 意見:學校: 有創意,通過!
[國家] 狀態:true 意見:省級: 還行,通過!
最終結果: true -- 國家: 勉強通過!

關鍵機制深度解析

機制說明
同步阻塞publishEvent 默認同步調用所有監聽器,線程阻塞直到最後一個返回。
順序保證Spring 根據 getOrder() 升序排序監聽器,同 Order 無序。
狀態傳遞事件對象在監聽器鏈中傳遞,可攜帶可變狀態 (如 status, advice)。
短路終止監聽器中設置 status=false,後續監聽器判斷跳過,實現「一票否決」。
類型過濾supportsEventType/SourceType 避免無關事件誤觸發,提升性能與安全性。

異步化擴展 (如需非阻塞)

@Configuration
@EnableAsync
public class AsyncEventConfig {
    @Bean
    public ApplicationEventMulticaster applicationEventMulticaster(TaskExecutor executor) {
        SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
        multicaster.setTaskExecutor(executor); // 異步執行
        return multicaster;
    }
}

// 監聽器添加 @Async
@Component
public class AsyncSchoolListener implements SmartApplicationListener {
    @Async @Override public void onApplicationEvent(ApplicationEvent event) { ... }
}

注意:異步模式下失去順序保證與狀態傳遞語義,需引入消息隊列/狀態機框架協調。

對比:ApplicationListener vs SmartApplicationListener

特性ApplicationListenerSmartApplicationListener
順序控制無 (依賴 @Order 注解於類上,但不標準)getOrder() 標準接口
事件類型過濾泛型擦除導致運行時無法精準判斷supportsEventType() 精確判斷
事件源過濾無supportsSourceType() 精確判斷
適用場景簡單解耦、異步通知、日誌記錄有序流水線、狀態機、多級審批、管道過濾

總結

SmartApplicationListener 通過 getOrder()、類型過濾、同步阻塞發布,將 Spring 事件機制從「廣播通知」升級為「有序流水線處理器」。結合事件對象攜帶可變狀態,可優雅實現多級審核、數據清洗管道、初始化鏈等強順序業務場景,是 Spring 事件編程的進階利器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved