中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

Spring/SpringBoot事件監(jiān)聽機(jī)制是什么

本篇文章給大家分享的是有關(guān)Spring/SpringBoot 事件監(jiān)聽機(jī)制是什么,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

創(chuàng)新互聯(lián)公司成立與2013年,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢想脫穎而出為使命,1280元汝城做網(wǎng)站,已為上家服務(wù),為汝城各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:028-86922220

事件監(jiān)聽機(jī)制可以理解為是一種觀察者模式,有數(shù)據(jù)發(fā)布者(事件源)和數(shù)據(jù)接受者(監(jiān)聽器);

在Java中,事件對象都是繼承java.util.EventObject對象,事件監(jiān)聽器都是java.util.EventListener實(shí)例;

EventObject對象不提供默認(rèn)構(gòu)造器,需要外部傳遞source參數(shù),即用于記錄并跟蹤事件的來源;

Spring事件

Spring事件對象為ApplicationEvent,繼承EventObject,源碼如下:

public abstract class ApplicationEvent extends EventObject {      /**      * Create a new ApplicationEvent.      * @param source the object on which the event initially occurred (never {@code null})      */     public ApplicationEvent(Object source) {         super(source);         this.timestamp = System.currentTimeMillis();     }  }

Spring事件監(jiān)聽器為ApplicationListener,繼承EventListener, 源碼如下:

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {     void onApplicationEvent(E var1); }

實(shí)現(xiàn)Spring事件監(jiān)聽有兩種方式:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 面向接口編程,實(shí)現(xiàn)ApplicationListener接口;

  3. 基于注解驅(qū)動(dòng),@EventListener(Spring自定義的注解);

實(shí)例:

面向接口編程,實(shí)現(xiàn)ApplicationListener接口:

自定義事件對象:

public class MyApplicationEvent extends ApplicationEvent {     public MyApplicationEvent(Object source) {         super(source);     } }

自定義事件監(jiān)聽器:

public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {     @Override     public void onApplicationEvent(MyApplicationEvent event) {         System.out.println("收到事件:" + event);     } }

啟動(dòng)服務(wù)并發(fā)布事件:

public class ApplicationEventBootstrap {      public static void main(String[] args) {         AnnotationConfigApplicationContext context =                 new AnnotationConfigApplicationContext();         // 注冊自定義事件監(jiān)聽器         context.addApplicationListener(new MyApplicationListener());         // 啟動(dòng)上下文         context.refresh();         // 發(fā)布事件,事件源為Context         context.publishEvent(new MyApplicationEvent(context));         // 結(jié)束         context.close();     } }

運(yùn)行結(jié)果:

收到事件:com.xx.MyApplicationEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@cb0ed20, started on Sat May 16 16:32:04 CST 2020]

使用注解 @EventListener實(shí)現(xiàn)Spring事件監(jiān)聽:

@Component public class MyApplicationListener2 {      @EventListener(MyApplicationEvent.class)     public void onEvent(MyApplicationEvent event) {         System.out.println("收到事件:" + event);     } }

啟動(dòng)并發(fā)布事件:

public class ApplicationEventBootstrap {      public static void main(String[] args) {         AnnotationConfigApplicationContext context =                 new AnnotationConfigApplicationContext();         // 注冊自定義事件監(jiān)聽器         context.register(MyApplicationListener2.class);         // 啟動(dòng)上下文         context.refresh();         // 發(fā)布事件,事件源為Context         context.publishEvent(new MyApplicationEvent(context));         // 結(jié)束         context.close();     } }

運(yùn)行結(jié)果:

收到事件:com.xx.MyApplicationEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@cb0ed20, started on Sat May 16 16:32:04 CST 2020]

通過實(shí)例可以看出,上面兩種方式都可正常發(fā)布和接收事件。

實(shí)現(xiàn)原理

通過上面實(shí)例可以看出,context 可以發(fā)布事件,那底層是怎么發(fā)布的,讓我們繼續(xù)看源碼:

public abstract class AbstractApplicationContext extends DefaultResourceLoader         implements ConfigurableApplicationContext {       protected void publishEvent(Object event, @Nullable ResolvableType eventType) {         ...         getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);         ...       } }

通過源碼我們可以看出,事件應(yīng)該是通過

ApplicationEventMulticaster發(fā)布的,我們繼續(xù)看:

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster

Spring 中事件發(fā)布都是通過

SimpleApplicationEventMulticaster來實(shí)現(xiàn)的

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {         ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));         for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {             Executor executor = getTaskExecutor();             if (executor != null) {         // 異步                 executor.execute(() -> invokeListener(listener, event));             }             else {                 invokeListener(listener, event);             }         }     }

可以看出,如果設(shè)置了Executor則異步發(fā)送,否則同步;而且可以看出通過 resolveDefaultEventType(event)  對發(fā)布的事件類型進(jìn)行了校驗(yàn),這就是為什么我們可以直接使用泛型來指定我們想接收的事件對象, 比如上面的 ApplicationListener。

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {         try {             listener.onApplicationEvent(event);

最后就使用對應(yīng)的ApplicationListener進(jìn)行接收和處理就行了,那么ApplicationListener是什么時(shí)候注冊的呢?

如何添加ApplicationListener?

  1. 直接添加,使用content.addApplicationListener(上面實(shí)例中有使用);

  2. 將自定義的ApplicationListener注冊為一個(gè)Bean,Spring再初始化Bean之后會添加,具體代碼在ApplicationListenerDetector#postProcessAfterInitialization,判斷一個(gè)Bean如果是ApplicationListener,則也是使用context.addApplicationListener添加;

  3. 使用注解@EventListener,在初始化Bean之后,會在EventListenerMethodProcessor中進(jìn)行處理和添加;

第三種實(shí)現(xiàn)的源碼如下(

EventListenerMethodProcessor中):

private void processBean(final String beanName, final Class<?> targetType) {   ....   // 獲取public 且有@EventListener的方法    AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));   ...    ApplicationListener<?> applicationListener = factory.createApplicationListener(beanName, targetType, methodToUse);                    // 添加監(jiān)聽器   context.addApplicationListener(applicationListener);  }

Spring內(nèi)建事件

  • ContextRefreshedEvent: Spring應(yīng)用上下文就緒事件;

  • ContextStartedEvent: Spring應(yīng)用上下文啟動(dòng)事件;

  • ContextStopedEvent: Spring應(yīng)用上下文停止事件;

  • ContextClosedEvent: Spring應(yīng)用上下文關(guān)閉事件;

Spring Boot事件

Spring Boot事件是在Spring事件基礎(chǔ)上進(jìn)行的封裝

public abstract class SpringApplicationEvent extends ApplicationEvent

事件對象改為SpringApplicationEvent,事件源為SpringApplication(Spring事件源為Context);

底層發(fā)布事件還是使用

SimpleApplicationEventMulticaster 對象,不過有點(diǎn)需要說明的是,Spring Boot  1.4開始,SpringApplication和ApplicationContext使用的都是

SimpleApplicationEventMulticaster實(shí)例,但是兩者屬于不同的對象(1.0 ~ 1.3版本是同一個(gè)對象);

事件回顧:

public class EventBootstrap {      public static void main(String[] args) {         new SpringApplicationBuilder(Object.class)                 .listeners(event -> {                     System.out.println("事件對象:"                     + event.getClass().getSimpleName()                     + " ,事件源:" + event.getSource().getClass().getSimpleName());                 })                 .web(WebApplicationType.NONE)                 .run(args)                 .close();     } }

運(yùn)行結(jié)果:

事件對象:ApplicationContextInitializedEvent ,事件源:SpringApplication 事件對象:ApplicationPreparedEvent ,事件源:SpringApplication 事件對象:ContextRefreshedEvent ,事件源:AnnotationConfigApplicationContext 事件對象:ApplicationStartedEvent ,事件源:SpringApplication 事件對象:ApplicationReadyEvent ,事件源:SpringApplication 事件對象:ContextClosedEvent ,事件源:AnnotationConfigApplicationContext

從結(jié)果可以看出,事件對象類型和事件源,以及事件發(fā)布順序。

以上就是Spring/SpringBoot 事件監(jiān)聽機(jī)制是什么,小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

當(dāng)前名稱:Spring/SpringBoot事件監(jiān)聽機(jī)制是什么
新聞來源:http://www.rwnh.cn/article44/ippihe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、品牌網(wǎng)站設(shè)計(jì)、虛擬主機(jī)、網(wǎng)站營銷、營銷型網(wǎng)站建設(shè)、關(guān)鍵詞優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名
龙川县| 武清区| 花莲县| 胶州市| 长岛县| 永济市| 迭部县| 仪陇县| 自治县| 安岳县| 万盛区| 台州市| 桂林市| 安多县| 太原市| 丰都县| 卓尼县| 华池县| 合肥市| 印江| 建平县| 边坝县| 德令哈市| 肥城市| 昆山市| 新龙县| 东莞市| 靖宇县| 正镶白旗| 彰化县| 瑞丽市| 营口市| 收藏| 三明市| 梁山县| 拉孜县| 五指山市| 宜黄县| 合川市| 潜江市| 安吉县|