色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

SpringBoot事件機(jī)制相關(guān)知識(shí)點(diǎn)匯總

瀏覽:63日期:2023-04-28 11:06:53

要“監(jiān)聽(tīng)”事件,我們總是可以將“監(jiān)聽(tīng)器”作為事件源中的另一個(gè)方法寫(xiě)入事件,但這將使事件源與監(jiān)聽(tīng)器的邏輯緊密耦合。

對(duì)于實(shí)際事件,我們比直接方法調(diào)用更靈活。我們可以根據(jù)需要?jiǎng)討B(tài)注冊(cè)和注銷(xiāo)某些事件的偵聽(tīng)器。我們還可以為同一事件設(shè)置多個(gè)偵聽(tīng)器。

本教程概述了如何發(fā)布和偵聽(tīng)自定義事件,并解釋了 Spring Boot 的內(nèi)置事件。

為什么我應(yīng)該使用事件而不是直接方法調(diào)用?

事件和直接方法調(diào)用都適合于不同的情況。使用方法調(diào)用,就像斷言一樣-無(wú)論發(fā)送和接收模塊的狀態(tài)如何,他們都需要知道此事件的發(fā)生。

對(duì)于事件,另一方面,我們只知道發(fā)生了一個(gè)事件,哪些模塊會(huì)被通知并不是我們關(guān)心的問(wèn)題。當(dāng)我們想要將某些業(yè)務(wù)處理傳遞給另一個(gè)線程時(shí)(例如:在某些任務(wù)完成時(shí)發(fā)送電子郵件),最好使用事件。此外,事件對(duì)于測(cè)試驅(qū)動(dòng)的開(kāi)發(fā)也很有用。

什么是應(yīng)用程序事件( Application Events)?

Spring 應(yīng)用程序事件允許我們發(fā)送和接收特定應(yīng)用程序事件,我們可以根據(jù)需要處理這些事件。事件用于在松散耦合的組件之間交換信息。由于發(fā)布者和訂閱者之間沒(méi)有直接耦合,因此可以在不影響發(fā)布者的情況下修改訂閱者,反之亦然。

讓我們看看如何在 Spring Boot 應(yīng)用程序中創(chuàng)建、發(fā)布和偵聽(tīng)自定義事件。

創(chuàng)建ApplicationEvent

我們可以使用 Spring Framework 的事件發(fā)布機(jī)制發(fā)布應(yīng)用程序事件。

讓我們通過(guò)擴(kuò)展來(lái)創(chuàng)建調(diào)用的自定義事件:

class UserCreatedEvent extends ApplicationEvent { private String name; UserCreatedEvent(Object source, String name) { super(source); this.name = name; } ...}

代碼中super(source)中的source應(yīng)該是最初發(fā)生事件的對(duì)象或與事件相關(guān)聯(lián)的對(duì)象。

從Spring 4.2開(kāi)始,我們還可以將對(duì)象發(fā)布為事件,而無(wú)需擴(kuò)展ApplicationEvent:

class UserRemovedEvent { private String name; UserRemovedEvent(String name) { this.name = name; } ...}

發(fā)布一個(gè)ApplicationEvent

我們使用ApplicationEventPublisher接口發(fā)布事件:

@Componentclass Publisher { private final ApplicationEventPublisher publisher; Publisher(ApplicationEventPublisher publisher) { this.publisher = publisher; } void publishEvent(final String name) { // Publishing event created by extending ApplicationEvent publisher.publishEvent(new UserCreatedEvent(this, name)); // Publishing an object as an event publisher.publishEvent(new UserRemovedEvent(name)); }}

當(dāng)我們發(fā)布的對(duì)象不是ApplicationEvent時(shí),Spring會(huì)自動(dòng)為我們將其包裝在PayloadApplicationEvent中。

接收應(yīng)用程序事件

現(xiàn)在,我們知道如何創(chuàng)建和發(fā)布自定義事件,讓我們看看如何偵聽(tīng)該事件。事件可以有多個(gè)偵聽(tīng)器并且根據(jù)應(yīng)用程序要求執(zhí)行不同的工作。

有兩種方法可以定義偵聽(tīng)器。我們可以使用注解(@EventListener)或?qū)崿F(xiàn)接口(ApplicationListener)。在這兩種情況下,偵聽(tīng)器類(lèi)都必須由 Spring 管理。

注解

從Spring 4.1開(kāi)始,可以使用@EventListener注解的方法,以自動(dòng)注冊(cè)與該方法簽名匹配的ApplicationListener:

@Componentclass UserRemovedListener { @EventListener ReturnedEvent handleUserRemovedEvent(UserRemovedEvent event) { // handle UserRemovedEvent ... return new ReturnedEvent(); } @EventListener void handleReturnedEvent(ReturnedEvent event) { // handle ReturnedEvent ... } ...}

啟用注解驅(qū)動(dòng)的配置時(shí),不需要其他配置。我們的方法可以監(jiān)聽(tīng)多個(gè)事件,或者如果我們想完全不使用任何參數(shù)來(lái)定義它,那么事件類(lèi)型也可以在注解本身上指定。示例:@EventListener({ContextStartedEvent.class,ContextRefreshedEvent.class})。

對(duì)于使用@EventListener注解并定義為具有返回類(lèi)型的方法,Spring會(huì)將結(jié)果作為新事件發(fā)布給我們。在上面的示例中,第一個(gè)方法返回的ReturnedEvent將被發(fā)布,然后由第二個(gè)方法處理。

如果指定SpEL條件,Spring僅在某些情況下才允許觸發(fā)我們的偵聽(tīng)器:

@Componentclass UserRemovedListener { @EventListener(condition = '#event.name eq ’reflectoring’') void handleConditionalListener(UserRemovedEvent event) { // handle UserRemovedEvent }}

僅當(dāng)表達(dá)式的計(jì)算結(jié)果為true或以下字符串之一時(shí)才處理該事件:“ true”,“ on”,“ yes”或“ 1”。方法參數(shù)通過(guò)其名稱公開(kāi)。條件表達(dá)式還公開(kāi)了一個(gè)“ root”變量,該變量引用原始ApplicationEvent(#root.event)和實(shí)際方法參數(shù)(#root.args)

在以上示例中,僅當(dāng)#event.name的值為’reflectoring’時(shí),才會(huì)使用UserRemovedEvent觸發(fā)監(jiān)聽(tīng)器。

實(shí)現(xiàn)ApplicationListener接口

偵聽(tīng)事件的另一種方法是實(shí)現(xiàn)ApplicationListener接口:

@Componentclass UserCreatedListener implements ApplicationListener<UserCreatedEvent> { @Override public void onApplicationEvent(UserCreatedEvent event) { // handle UserCreatedEvent }}

只要偵聽(tīng)器對(duì)象在Spring應(yīng)用程序上下文中注冊(cè),它就會(huì)接收事件。當(dāng)Spring路由一個(gè)事件時(shí),它使用偵聽(tīng)器的簽名來(lái)確定它是否與事件匹配。

異步事件偵聽(tīng)器

默認(rèn)情況下,spring事件是同步的,這意味著發(fā)布者線程將阻塞,直到所有偵聽(tīng)器都完成對(duì)事件的處理為止。

要使事件偵聽(tīng)器以異步模式運(yùn)行,我們要做的就是在該偵聽(tīng)器上使用@Async注解:

@Componentclass AsyncListener { @Async @EventListener void handleAsyncEvent(String event) { // handle event }}

為了使@Async注解起作用,我們還必須使用@EnableAsync注解我們的@Configuration類(lèi)之一或@SpringBootApplication類(lèi)。

上面的代碼示例還顯示了我們可以將String用作事件。使用風(fēng)險(xiǎn)自負(fù)。最好使用特定于我們用例的數(shù)據(jù)類(lèi)型,以免與其他事件沖突。

Transaction-綁定事件

Spring允許我們將事件偵聽(tīng)器綁定到當(dāng)前事務(wù)的某個(gè)階段。如果當(dāng)前事務(wù)的結(jié)果對(duì)偵聽(tīng)器很重要時(shí),這使事件可以更靈活地使用。

當(dāng)我們使用@TransactionalEventListener注釋方法時(shí),我們將獲得一個(gè)擴(kuò)展的事件偵聽(tīng)器,該偵聽(tīng)器可以了解事務(wù):

@Componentclass UserRemovedListener { @TransactionalEventListener(phase=TransactionPhase.AFTER_COMPLETION) void handleAfterUserRemoved(UserRemovedEvent event) { // handle UserRemovedEvent }}

僅當(dāng)當(dāng)前事務(wù)完成時(shí)才調(diào)用UserRemovedListener。

我們可以將偵聽(tīng)器綁定到事務(wù)的以下階段:

AFTER_COMMIT:事務(wù)成功提交后,將處理該事件。如果事件偵聽(tīng)器僅在當(dāng)前事務(wù)成功時(shí)才運(yùn)行,則可以使用此方法。

AFTER_COMPLETION:事務(wù)提交或回滾時(shí)將處理該事件。例如,我們可以使用它在事務(wù)完成后執(zhí)行清理。

AFTER_ROLLBACK:事務(wù)回滾后將處理該事件。

BEFORE_COMMIT:該事件將在事務(wù)提交之前進(jìn)行處理。例如,我們可以使用它來(lái)將事務(wù)性O(shè)RM會(huì)話刷新到數(shù)據(jù)庫(kù)。

Spring Boot的 Application Events

Spring Boot提供了幾個(gè)與SpringApplication生命周期相關(guān)的預(yù)定義ApplicationEvent。

在創(chuàng)建ApplicationContext之前會(huì)觸發(fā)一些事件,因此我們無(wú)法將這些事件注冊(cè)為@Bean。我們可以通過(guò)手動(dòng)添加偵聽(tīng)器來(lái)注冊(cè)這些事件的偵聽(tīng)器:

@SpringBootApplicationpublic class EventsDemoApplication { public static void main(String[] args) { SpringApplication springApplication = new SpringApplication(EventsDemoApplication.class); springApplication.addListeners(new SpringBuiltInEventsListener()); springApplication.run(args); }}

通過(guò)將META-INF/spring.factories文件添加到我們的項(xiàng)目中,我們還可以注冊(cè)偵聽(tīng)器,而不管如何創(chuàng)建應(yīng)用程序,并使用

org.springframework.context.ApplicationListener鍵引用偵聽(tīng)器:

org.springframework.context.ApplicationListener= com.reflectoring.eventdemo.SpringBuiltInEventsListener

class SpringBuiltInEventsListener implements ApplicationListener<SpringApplicationEvent>{ @Override public void onApplicationEvent(SpringApplicationEvent event) { // handle event }}

確定事件監(jiān)聽(tīng)器已正確注冊(cè)后,便可以監(jiān)聽(tīng)所有Spring Boot的SpringApplicationEvents。讓我們按照它們?cè)趹?yīng)用程序啟動(dòng)過(guò)程中的執(zhí)行順序來(lái)進(jìn)行觀察。

ApplicationStartingEvent

除了運(yùn)行偵聽(tīng)器和初始化程序的注冊(cè)之外,ApplicationStartingEvent在運(yùn)行開(kāi)始時(shí)但在任何處理之前都會(huì)觸發(fā)。

ApplicationEnvironmentPreparedEvent

當(dāng)上下文中使用的環(huán)境可用時(shí),將觸發(fā)ApplicationEnvironmentPreparedEvent。

由于此時(shí)環(huán)境已準(zhǔn)備就緒,因此我們可以在其他Bean使用它之前對(duì)其進(jìn)行檢查和修改。

ApplicationContextInitializedEvent

當(dāng)ApplicationContext準(zhǔn)備就緒并且調(diào)用ApplicationContextInitializers但尚未加載bean定義時(shí),將觸發(fā)ApplicationContextInitializedEvent。

在bean初始化到Spring容器之前,我們可以使用它來(lái)執(zhí)行任務(wù)。

ApplicationPreparedEvent

準(zhǔn)備好ApllicationContext但未刷新時(shí)會(huì)觸發(fā)ApplicationPreparedEvent。

該環(huán)境已準(zhǔn)備就緒,可以使用,并且將加載Bean定義。

WebServerInitializedEvent

如果我們使用的是網(wǎng)絡(luò)服務(wù)器,則在網(wǎng)絡(luò)服務(wù)器準(zhǔn)備就緒后會(huì)觸發(fā)WebServerInitializedEvent。 ServletWebServerInitializedEvent和ReactiveWebServerInitializedEvent分別是servlet和反應(yīng)式網(wǎng)絡(luò)服務(wù)。

WebServerInitializedEvent不擴(kuò)展SpringApplicationEvent。

ApplicationStartedEvent

在刷新上下文之后但在調(diào)用任何應(yīng)用程序和命令行運(yùn)行程序之前,將觸發(fā)ApplicationStartedEvent。

ApplicationReadyEvent

觸發(fā)ApplicationReadyEvent來(lái)指示該應(yīng)用程序已準(zhǔn)備就緒,可以處理請(qǐng)求。

建議此時(shí)不要修改內(nèi)部狀態(tài),因?yàn)樗谐跏蓟襟E都將完成。

ApplicationFailedEvent

如果存在異常并且應(yīng)用程序無(wú)法啟動(dòng),則會(huì)觸發(fā)ApplicationFailedEvent。在啟動(dòng)期間的任何時(shí)間都可能發(fā)生這種情況。

我們可以使用它來(lái)執(zhí)行一些任務(wù),例如執(zhí)行腳本或在啟動(dòng)失敗時(shí)發(fā)出通知。

結(jié)論

事件是為在同一應(yīng)用程序上下文內(nèi)的Spring Bean之間進(jìn)行簡(jiǎn)單通信而設(shè)計(jì)的。從Spring 4.2開(kāi)始,基礎(chǔ)結(jié)構(gòu)已得到顯著改進(jìn),并提供了基于注釋的模型以及發(fā)布任意事件的功能。

英文原文:https://reflectoring.io/spring-boot-application-events-explained/

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 波多野结衣一区二区三区88 | 欧美一级大黄特黄毛片视频 | a级免费| 欧美精品久久天天躁 | 精品一区二区三区亚洲 | 精品一区二区三区三区 | 九草视频 | 毛片图片 | 99久久精品免费观看区一 | 国产精品18久久久久久久久久 | 又黄又爽视频好爽视频 | 久久久久久国产精品视频 | 全部在线美女网站免费观看 | 国产a级三级三级三级 | 亚洲综合色视频在线观看 | 国产精品二区三区免费播放心 | 国产精品日本欧美一区二区 | 国产欧美日韩免费一区二区 | 国内欧美一区二区三区 | 日本在线看小视频网址 | 欧美日韩一区二区中文字幕视频 | 99视频精品| 三级网址在线观看 | 5388国产亚洲欧美在线观看 | 色网址在线观看 | 成年人网站免费在线观看 | 免费一级做a爰片性色毛片 免费一极毛片 | 特级毛片aaaa免费观看 | 99久久免费午夜国产精品 | 加勒比毛片 | 欧美一级日韩一级亚洲一级 | 国内自拍视频在线播放 | 97在线免费视频观看 | a在线观看欧美在线观看 | 国产高清在线精品一区二区三区 | 亚洲男人的天堂成人 | 在线观看偷拍视频一区 | 欧美操操操 | 草草影院www色欧美极品 | caoporen国产91在线 | 国产乱纶 |