您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關Spring/SpringBoot 事件監聽機制是什么,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
事件監聽機制可以理解為是一種觀察者模式,有數據發布者(事件源)和數據接受者(監聽器);
在Java中,事件對象都是繼承java.util.EventObject對象,事件監聽器都是java.util.EventListener實例;
EventObject對象不提供默認構造器,需要外部傳遞source參數,即用于記錄并跟蹤事件的來源;
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事件監聽器為ApplicationListener,繼承EventListener, 源碼如下:
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { void onApplicationEvent(E var1); }
實現Spring事件監聽有兩種方式:
鴻蒙官方戰略合作共建——HarmonyOS技術社區
面向接口編程,實現ApplicationListener接口;
基于注解驅動,@EventListener(Spring自定義的注解);
實例:
面向接口編程,實現ApplicationListener接口:
自定義事件對象:
public class MyApplicationEvent extends ApplicationEvent { public MyApplicationEvent(Object source) { super(source); } }
自定義事件監聽器:
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> { @Override public void onApplicationEvent(MyApplicationEvent event) { System.out.println("收到事件:" + event); } }
啟動服務并發布事件:
public class ApplicationEventBootstrap { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // 注冊自定義事件監聽器 context.addApplicationListener(new MyApplicationListener()); // 啟動上下文 context.refresh(); // 發布事件,事件源為Context context.publishEvent(new MyApplicationEvent(context)); // 結束 context.close(); } }
運行結果:
收到事件:com.xx.MyApplicationEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@cb0ed20, started on Sat May 16 16:32:04 CST 2020]
使用注解 @EventListener實現Spring事件監聽:
@Component public class MyApplicationListener2 { @EventListener(MyApplicationEvent.class) public void onEvent(MyApplicationEvent event) { System.out.println("收到事件:" + event); } }
啟動并發布事件:
public class ApplicationEventBootstrap { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // 注冊自定義事件監聽器 context.register(MyApplicationListener2.class); // 啟動上下文 context.refresh(); // 發布事件,事件源為Context context.publishEvent(new MyApplicationEvent(context)); // 結束 context.close(); } }
運行結果:
收到事件:com.xx.MyApplicationEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@cb0ed20, started on Sat May 16 16:32:04 CST 2020]
通過實例可以看出,上面兩種方式都可正常發布和接收事件。
實現原理
通過上面實例可以看出,context 可以發布事件,那底層是怎么發布的,讓我們繼續看源碼:
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { protected void publishEvent(Object event, @Nullable ResolvableType eventType) { ... getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); ... } }
通過源碼我們可以看出,事件應該是通過
ApplicationEventMulticaster發布的,我們繼續看:
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster
Spring 中事件發布都是通過
SimpleApplicationEventMulticaster來實現的
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); } } }
可以看出,如果設置了Executor則異步發送,否則同步;而且可以看出通過 resolveDefaultEventType(event) 對發布的事件類型進行了校驗,這就是為什么我們可以直接使用泛型來指定我們想接收的事件對象, 比如上面的 ApplicationListener。
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { try { listener.onApplicationEvent(event);
最后就使用對應的ApplicationListener進行接收和處理就行了,那么ApplicationListener是什么時候注冊的呢?
如何添加ApplicationListener?
直接添加,使用content.addApplicationListener(上面實例中有使用);
將自定義的ApplicationListener注冊為一個Bean,Spring再初始化Bean之后會添加,具體代碼在ApplicationListenerDetector#postProcessAfterInitialization,判斷一個Bean如果是ApplicationListener,則也是使用context.addApplicationListener添加;
使用注解@EventListener,在初始化Bean之后,會在EventListenerMethodProcessor中進行處理和添加;
第三種實現的源碼如下(
EventListenerMethodProcessor中):
private void processBean(final String beanName, final Class<?> targetType) { .... // 獲取public 且有@EventListener的方法 AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class)); ... ApplicationListener<?> applicationListener = factory.createApplicationListener(beanName, targetType, methodToUse); // 添加監聽器 context.addApplicationListener(applicationListener); }
Spring內建事件
ContextRefreshedEvent: Spring應用上下文就緒事件;
ContextStartedEvent: Spring應用上下文啟動事件;
ContextStopedEvent: Spring應用上下文停止事件;
ContextClosedEvent: Spring應用上下文關閉事件;
Spring Boot事件
Spring Boot事件是在Spring事件基礎上進行的封裝
public abstract class SpringApplicationEvent extends ApplicationEvent
事件對象改為SpringApplicationEvent,事件源為SpringApplication(Spring事件源為Context);
底層發布事件還是使用
SimpleApplicationEventMulticaster 對象,不過有點需要說明的是,Spring Boot 1.4開始,SpringApplication和ApplicationContext使用的都是
SimpleApplicationEventMulticaster實例,但是兩者屬于不同的對象(1.0 ~ 1.3版本是同一個對象);
事件回顧:
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(); } }
運行結果:
事件對象:ApplicationContextInitializedEvent ,事件源:SpringApplication 事件對象:ApplicationPreparedEvent ,事件源:SpringApplication 事件對象:ContextRefreshedEvent ,事件源:AnnotationConfigApplicationContext 事件對象:ApplicationStartedEvent ,事件源:SpringApplication 事件對象:ApplicationReadyEvent ,事件源:SpringApplication 事件對象:ContextClosedEvent ,事件源:AnnotationConfigApplicationContext
從結果可以看出,事件對象類型和事件源,以及事件發布順序。
以上就是Spring/SpringBoot 事件監聽機制是什么,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。