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

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

 更新時間:2020年09月03日 11:31:24   作者:東溪陳姓少年  
這篇文章主要介紹了SpringBoot事件機(jī)制相關(guān)知識點匯總,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

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

對于實際事件,我們比直接方法調(diào)用更靈活。我們可以根據(jù)需要動態(tài)注冊和注銷某些事件的偵聽器。我們還可以為同一事件設(shè)置多個偵聽器。

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

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

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

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

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

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

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

創(chuàng)建ApplicationEvent

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

讓我們通過擴(kuò)展來創(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ā)生事件的對象或與事件相關(guān)聯(lián)的對象。

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

class UserRemovedEvent {
 private String name;

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

發(fā)布一個ApplicationEvent

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

@Component
class 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ā)布的對象不是ApplicationEvent時,Spring會自動為我們將其包裝在PayloadApplicationEvent中。

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

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

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

注解

從Spring 4.1開始,可以使用@EventListener注解的方法,以自動注冊與該方法簽名匹配的ApplicationListener:

@Component
class UserRemovedListener {

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

 @EventListener
 void handleReturnedEvent(ReturnedEvent event) {
    // handle ReturnedEvent ...
 }
 ...
}

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

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

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

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

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

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

實現(xiàn)ApplicationListener接口

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

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

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

異步事件偵聽器

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

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

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

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

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

Transaction-綁定事件

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

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

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

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

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

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

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

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

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

Spring Boot的 Application Events

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

在創(chuàng)建ApplicationContext之前會觸發(fā)一些事件,因此我們無法將這些事件注冊為@Bean。我們可以通過手動添加偵聽器來注冊這些事件的偵聽器:

@SpringBootApplication
public class EventsDemoApplication {

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

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

org.springframework.context.ApplicationListener鍵引用偵聽器:

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

class SpringBuiltInEventsListener 
  implements ApplicationListener<SpringApplicationEvent>{

 @Override
 public void onApplicationEvent(SpringApplicationEvent event) {
  // handle event
 }
}

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

ApplicationStartingEvent

除了運(yùn)行偵聽器和初始化程序的注冊之外,ApplicationStartingEvent在運(yùn)行開始時但在任何處理之前都會觸發(fā)。

ApplicationEnvironmentPreparedEvent

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

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

ApplicationContextInitializedEvent

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

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

ApplicationPreparedEvent

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

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

WebServerInitializedEvent

如果我們使用的是網(wǎng)絡(luò)服務(wù)器,則在網(wǎng)絡(luò)服務(wù)器準(zhǔn)備就緒后會觸發(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來指示該應(yīng)用程序已準(zhǔn)備就緒,可以處理請求。

建議此時不要修改內(nèi)部狀態(tài),因為所有初始化步驟都將完成。

ApplicationFailedEvent

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

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

結(jié)論

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

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

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java?LocalDateTime獲取時間信息、格式化、轉(zhuǎn)換為數(shù)字時間戳代碼示例

    Java?LocalDateTime獲取時間信息、格式化、轉(zhuǎn)換為數(shù)字時間戳代碼示例

    其實我們在Java項目中對日期進(jìn)行格式化,主要是利用一些日期格式化類,下面這篇文章主要給大家介紹了關(guān)于Java?LocalDateTime獲取時間信息、格式化、轉(zhuǎn)換為數(shù)字時間戳的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • Spring的@Scope注解詳細(xì)解析

    Spring的@Scope注解詳細(xì)解析

    這篇文章主要介紹了Spring的@Scope注解詳細(xì)解析,@Scope注解主要作用是調(diào)節(jié)Ioc容器中的作用域,springboot?程序啟動時會對classpath路徑下的包中的類進(jìn)行掃描,將類解析成BeanDefinition,需要的朋友可以參考下
    2023-11-11
  • Java生產(chǎn)者消費(fèi)者模式實例分析

    Java生產(chǎn)者消費(fèi)者模式實例分析

    這篇文章主要介紹了Java生產(chǎn)者消費(fèi)者模式,結(jié)合實例形式分析了java生產(chǎn)者消費(fèi)者模式的相關(guān)組成、原理及實現(xiàn)方法,需要的朋友可以參考下
    2019-03-03
  • Java代理的幾種實現(xiàn)方式總結(jié)

    Java代理的幾種實現(xiàn)方式總結(jié)

    本文將通過例子說明java代理的幾種實現(xiàn)方式,并比較它們之間的差異,文中通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的參考價值,需要的朋友可以參考下
    2023-12-12
  • Java中泛型通配符的使用方法示例

    Java中泛型通配符的使用方法示例

    這篇文章主要介紹了Java中泛型通配符的使用方法,結(jié)合實例形式分析了java中泛型通配符的功能、語法及在泛型類創(chuàng)建泛型對象中的使用方法,需要的朋友可以參考下
    2019-08-08
  • MyBatis通用Mapper中的通用example(排序)詳解

    MyBatis通用Mapper中的通用example(排序)詳解

    這篇文章主要介紹了MyBatis通用Mapper中的通用example(排序)詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 基于Java創(chuàng)建一個訂單類代碼實例

    基于Java創(chuàng)建一個訂單類代碼實例

    這篇文章主要介紹了基于Java創(chuàng)建一個訂單類代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • Java中Map.merge()方法使用示例詳解

    Java中Map.merge()方法使用示例詳解

    這篇文章主要介紹了Map.merge()方法使用和介紹,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • spring-boot中spring-boot-maven-plugin報紅錯誤及解決

    spring-boot中spring-boot-maven-plugin報紅錯誤及解決

    這篇文章主要介紹了spring-boot中spring-boot-maven-plugin報紅錯誤及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • maven一鍵刪除倉庫無用文件的實現(xiàn)

    maven一鍵刪除倉庫無用文件的實現(xiàn)

    大家都知道我們在使用Maven的時候,會下載一堆無用非jar文件,本文主要介紹了maven一鍵刪除倉庫無用文件的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2023-11-11

最新評論