欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java Spring ApplicationEvent 代碼示例解析

 更新時(shí)間:2025年06月17日 17:10:38   作者:兔子蟹子  
本文解析了Spring事件機(jī)制,涵蓋核心概念(發(fā)布-訂閱/觀察者模式)、代碼實(shí)現(xiàn)(事件定義、發(fā)布、監(jiān)聽)及高級(jí)應(yīng)用(異步處理、事務(wù)綁定、執(zhí)行順序),對(duì)Java Spring ApplicationEvent概念相關(guān)知識(shí)感興趣的朋友一起看看吧

一、Spring 事件機(jī)制核心概念

1. 事件驅(qū)動(dòng)架構(gòu)模型

  • 發(fā)布-訂閱模式:解耦事件生產(chǎn)者和消費(fèi)者
  • 觀察者模式:監(jiān)聽器監(jiān)聽特定事件
  • 事件驅(qū)動(dòng)優(yōu)勢(shì)
    • 組件間松耦合
    • 系統(tǒng)擴(kuò)展性好
    • 支持異步處理
    • 事件溯源支持

2. 核心組件

組件作用實(shí)現(xiàn)方式
ApplicationEvent事件基類自定義事件需繼承
ApplicationEventPublisher事件發(fā)布接口通過(guò)Spring容器注入
ApplicationListener事件監(jiān)聽接口實(shí)現(xiàn)接口或使用@EventListener

二、代碼示例解析

1. 事件定義 (KnowledgeService.java)

@Getter
public static final class ImportedKnowledgeEvent extends ApplicationEvent {
    private final Knowledge knowledge;
    private final KWDocument document;
    // 構(gòu)造器1:只有knowledge
    public ImportedKnowledgeEvent(Object source, Knowledge knowledge) {
        super(source);
        this.knowledge = knowledge;
        this.document = null;
    }
    // 構(gòu)造器2:knowledge + document
    public ImportedKnowledgeEvent(Object source, Knowledge knowledge, KWDocument document) {
        super(source);
        this.knowledge = knowledge;
        this.document = document;
    }
}

關(guān)鍵點(diǎn)

  • 繼承ApplicationEvent基類
  • 使用final字段保證事件不可變性
  • 提供多種構(gòu)造器支持不同場(chǎng)景
  • 使用@Getter(Lombok)提供訪問(wèn)方法

2. 事件發(fā)布 (KnowledgeService.java)

@Service
public class KnowledgeService {
    @Autowired
    protected ApplicationEventPublisher eventPublisher;
    public void imports() {
        // 發(fā)布簡(jiǎn)單知識(shí)導(dǎo)入事件
        eventPublisher.publishEvent(new ImportedKnowledgeEvent(this, new Knowledge()));
        // 發(fā)布知識(shí)+文檔導(dǎo)入事件
        eventPublisher.publishEvent(new ImportedKnowledgeEvent(this, new Knowledge(), new KWDocument()));
    }
}

發(fā)布模式

  • 注入ApplicationEventPublisher
  • 創(chuàng)建事件對(duì)象(包含業(yè)務(wù)數(shù)據(jù))
  • 調(diào)用publishEvent()發(fā)布
  • 支持多種事件類型重載

3. 事件監(jiān)聽 (KnowledgeRagflowService.java)

@Service
public class KnowledgeRagflowService extends KnowledgeService {
    @EventListener
    public void importedKnowledge(KnowledgeService.ImportedKnowledgeEvent event) {
        if (event.getDocument() != null) {
            dealDocument(event.getKnowledge(), event.getDocument());
        } else {
            dealKnowledge(event.getKnowledge());
        }
    }
    private void dealDocument(Knowledge knowledge, Document document) {
        // 處理文檔邏輯
    }
    private void dealKnowledge(Knowledge knowledge) {
        // 處理知識(shí)邏輯
    }
}

監(jiān)聽器特點(diǎn)

  • 使用@EventListener注解簡(jiǎn)化實(shí)現(xiàn)
  • 方法參數(shù)決定監(jiān)聽的事件類型
  • 支持事件內(nèi)容判斷(區(qū)分有無(wú)document)
  • 私有方法封裝具體處理邏輯

三、高級(jí)應(yīng)用技巧

1. 條件監(jiān)聽

@EventListener(condition = "#event.document != null")
public void handleDocumentEvent(ImportedKnowledgeEvent event) {
    // 僅處理包含document的事件
}

2. 異步事件處理

@Async
@EventListener
public void asyncHandleEvent(ImportedKnowledgeEvent event) {
    // 異步處理耗時(shí)操作
}

配置要求

  • 主類添加@EnableAsync
  • 配置線程池:
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(25);
        executor.initialize();
        return executor;
    }
}

3. 監(jiān)聽器執(zhí)行順序

@Order(1)
@EventListener
public void firstListener(ImportedKnowledgeEvent event) {
    // 最先執(zhí)行
}
@Order(2)
@EventListener
public void secondListener(ImportedKnowledgeEvent event) {
    // 其次執(zhí)行
}

4. 事務(wù)綁定事件

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void afterCommitEvent(ImportedKnowledgeEvent event) {
    // 事務(wù)提交后執(zhí)行
}

事務(wù)階段選項(xiàng)

  • AFTER_COMMIT(默認(rèn)):事務(wù)成功提交后
  • AFTER_ROLLBACK:事務(wù)回滾后
  • AFTER_COMPLETION:事務(wù)完成后(提交或回滾)
  • BEFORE_COMMIT:事務(wù)提交前

四、最佳實(shí)踐

1. 事件設(shè)計(jì)原則

  • 單一職責(zé):一個(gè)事件只攜帶一種業(yè)務(wù)變更
  • 不可變性:事件發(fā)布后內(nèi)容不可修改
  • 上下文完整:包含所有必要業(yè)務(wù)數(shù)據(jù)
  • 命名規(guī)范:使用過(guò)去時(shí)態(tài)(如ImportedKnowledgeEvent

2. 性能優(yōu)化

  • 同步/異步選擇

  • 批量處理:對(duì)高頻事件進(jìn)行批量合并
  • 事件過(guò)濾:在監(jiān)聽器內(nèi)部添加條件判斷

3. 錯(cuò)誤處理

@EventListener
public void handleEvent(ImportedKnowledgeEvent event) {
    try {
        // 業(yè)務(wù)處理
    } catch (Exception e) {
        // 1. 記錄錯(cuò)誤日志
        // 2. 發(fā)布錯(cuò)誤處理事件
        // 3. 重試機(jī)制(如Spring Retry)
    }
}

4. 測(cè)試策略

@SpringBootTest
class KnowledgeEventTest {
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    @MockBean
    private KnowledgeRagflowService ragflowService;
    @Test
    void shouldTriggerListenerWhenPublishEvent() {
        // 準(zhǔn)備測(cè)試事件
        ImportedKnowledgeEvent event = new ImportedKnowledgeEvent(this, new Knowledge());
        // 發(fā)布事件
        eventPublisher.publishEvent(event);
        // 驗(yàn)證監(jiān)聽器調(diào)用
        verify(ragflowService, timeout(1000)).importedKnowledge(event);
    }
}

五、典型應(yīng)用場(chǎng)景

  • 業(yè)務(wù)狀態(tài)變更通知

    • 知識(shí)導(dǎo)入完成通知
    • 文檔處理狀態(tài)更新
  • 跨模塊協(xié)作

    • 知識(shí)導(dǎo)入后觸發(fā)索引更新
    • 文檔處理完成后通知搜索服務(wù)

系統(tǒng)生命周期事件

@EventListener
public void onApplicationReady(ContextRefreshedEvent event) {
    // 應(yīng)用啟動(dòng)完成后初始化資源
}

審計(jì)日志記錄

@EventListener
public void auditLog(ImportedKnowledgeEvent event) {
    log.info("Knowledge imported: {}", event.getKnowledge().getId());
}
  • 業(yè)務(wù)流程編排

六、常見問(wèn)題解決方案

  • 監(jiān)聽器未觸發(fā)

    • 檢查事件類型是否匹配
    • 確認(rèn)監(jiān)聽器在Spring容器中
    • 驗(yàn)證事件是否成功發(fā)布

循環(huán)事件觸發(fā)

// 使用標(biāo)記防止循環(huán)
public void imports() {
    if (!EventContext.isEventProcessing()) {
        eventPublisher.publishEvent(...);
    }
}
  • 事件數(shù)據(jù)過(guò)大

    • 改為傳遞引用ID而非整個(gè)對(duì)象
    • 使用DTO精簡(jiǎn)數(shù)據(jù)
    • 添加@Lazy注解延遲加載
  • 監(jiān)聽器執(zhí)行順序問(wèn)題

    • 使用@Order明確順序
    • 拆分事件避免依賴

總結(jié)

Spring ApplicationEvent 提供了強(qiáng)大的事件驅(qū)動(dòng)編程模型,通過(guò)示例中的KnowledgeServiceKnowledgeRagflowService展示了:

  • 如何定義包含業(yè)務(wù)數(shù)據(jù)的事件
  • 多種事件發(fā)布方式
  • 使用@EventListener簡(jiǎn)化監(jiān)聽器實(shí)現(xiàn)
  • 根據(jù)事件內(nèi)容執(zhí)行不同處理邏輯

在實(shí)際應(yīng)用中,應(yīng)結(jié)合:

  • 異步處理提升性能
  • 事務(wù)綁定確保數(shù)據(jù)一致性
  • 條件過(guò)濾優(yōu)化事件處理
  • 完善錯(cuò)誤處理機(jī)制

遵循"高內(nèi)聚、低耦合"原則,合理使用事件驅(qū)動(dòng)架構(gòu),可以顯著提升系統(tǒng)的擴(kuò)展性和可維護(hù)性。

到此這篇關(guān)于Java Spring ApplicationEvent 代碼示例解析的文章就介紹到這了,更多相關(guān)Spring ApplicationEvent 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java利用CompletionService保證任務(wù)先完成先獲取到執(zhí)行結(jié)果

    java利用CompletionService保證任務(wù)先完成先獲取到執(zhí)行結(jié)果

    這篇文章主要為大家詳細(xì)介紹了java如何利用CompletionService來(lái)保證任務(wù)先完成先獲取到執(zhí)行結(jié)果,文中的示例代碼講解詳細(xì),需要的可以參考下
    2023-08-08
  • Java簡(jiǎn)單使用EasyExcel操作讀寫excel的步驟與要點(diǎn)

    Java簡(jiǎn)單使用EasyExcel操作讀寫excel的步驟與要點(diǎn)

    相信現(xiàn)在很多搞后端的同學(xué)大部分做的都是后臺(tái)管理系統(tǒng),那么管理系統(tǒng)就肯定免不了Excel的導(dǎo)出導(dǎo)入功能,下面這篇文章主要給大家介紹了關(guān)于Java簡(jiǎn)單使用EasyExcel操作讀寫excel的步驟與要點(diǎn),需要的朋友可以參考下
    2022-09-09
  • Java系統(tǒng)環(huán)境變量配置全過(guò)程

    Java系統(tǒng)環(huán)境變量配置全過(guò)程

    本文介紹了如何配置Windows系統(tǒng)中的PATH和CLASSPATH環(huán)境變量,以及如何使用這些變量來(lái)運(yùn)行Java程序,步驟包括查看系統(tǒng)屬性、編輯環(huán)境變量、添加路徑、驗(yàn)證設(shè)置等,通過(guò)這些步驟,用戶可以永久性地保存PATH和CLASSPATH環(huán)境變量的設(shè)置,從而方便地運(yùn)行Java程序
    2024-11-11
  • SpringBoot @PathVariable使用時(shí)遇到的問(wèn)題及解決

    SpringBoot @PathVariable使用時(shí)遇到的問(wèn)題及解決

    這篇文章主要介紹了SpringBoot @PathVariable使用時(shí)遇到的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • SpringMVC文件上傳中要解決的問(wèn)題大匯總

    SpringMVC文件上傳中要解決的問(wèn)題大匯總

    這篇文章主要介紹了SpringMVC文件上傳中要解決的問(wèn)題,主要有中文文件名編碼問(wèn)題,文件位置存儲(chǔ)問(wèn)題以及文件名沖突問(wèn)題等等,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • SpringBoot整合Lettuce redis過(guò)程解析

    SpringBoot整合Lettuce redis過(guò)程解析

    這篇文章主要介紹了SpringBoot整合Lettuce redis過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • MacBook Java開發(fā)環(huán)境搭建的詳細(xì)步驟(新手必備)

    MacBook Java開發(fā)環(huán)境搭建的詳細(xì)步驟(新手必備)

    本文主要介紹了MacBook Java開發(fā)環(huán)境搭建,文中通過(guò)圖文示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Java實(shí)現(xiàn)http請(qǐng)求文件流對(duì)帶寬限速獲取md5值

    Java實(shí)現(xiàn)http請(qǐng)求文件流對(duì)帶寬限速獲取md5值

    文章介紹了如何在進(jìn)行HTTP請(qǐng)求下載大數(shù)據(jù)時(shí)處理帶寬限制和并發(fā)問(wèn)題,通過(guò)使用緩沖區(qū)和限速邏輯,可以有效控制下載速度,避免掉包和數(shù)據(jù)丟失,核心公式基于帶寬和已下載字節(jié)數(shù)計(jì)算預(yù)期耗時(shí),并通過(guò)Thread.sleep()進(jìn)行動(dòng)態(tài)休眠補(bǔ)償,感興趣的朋友一起看看吧
    2025-02-02
  • java工具類之實(shí)現(xiàn)java獲取文件行數(shù)

    java工具類之實(shí)現(xiàn)java獲取文件行數(shù)

    這篇文章主要介紹了一個(gè)java工具類,可以取得當(dāng)前項(xiàng)目中所有java文件總行數(shù),代碼行數(shù),注釋行數(shù),空白行數(shù),需要的朋友可以參考下
    2014-03-03
  • 單例模式的反射漏洞和反序列化漏洞代碼實(shí)例

    單例模式的反射漏洞和反序列化漏洞代碼實(shí)例

    這篇文章主要介紹了單例模式的反射漏洞和反序列化漏洞,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04

最新評(píng)論