在前面講到了bean的拓展,這篇文章將講述事件的拓展java
ApplicationListener 是用來監聽容器中發生的事件,只要事件發生,就會觸發監聽器的回調,完成事件驅動模型的開發spring
這裏經過兩個問題來進行概述,什麼是事件?spring是如何實現的?markdown
【1】什麼是事件app
事件是能夠被控件識別的操做,如按下肯定按鈕,選擇某個單選按鈕或者複選框。每一種控件有本身能夠識別的事件,如窗體的加載、單擊、雙擊等事件,編輯框(文本框)的文本改變事,等等。事件有系統事件和用戶事件。系統事件由系統激發,如時間每隔24小時,銀行儲戶的存款日期增長一天。用戶事件由用戶激發,如用戶點擊按鈕,在文本框中顯示特定的文本。事件驅動控件執行某項功能。異步
【2】如何實現源碼分析
Spring對事件機制也提供了支持,一個事件被髮布後,被對應的監聽器監聽到,執行對應方法。而且Spring內已經提供了許多事件,ApplicationEvent能夠說是Spring事件的頂級父類。ApplicationListener 是監聽器的頂級接口,事件被觸發後,onApplicationEvent方法就會執行測試
若是咱們要寫監聽器,就要寫這個監聽器接口的實現類,ApplicationEvent泛型就是咱們要監聽的類,因此咱們要監聽或者是發佈,都是ApplicationEvent及其下面的子事件,經過查看ApplicationEvent類,咱們發現有如下子事件:this
實現步驟:spa
// 啓動測試類
@Test
public void TestMain(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
// 本身發佈一個事件
applicationContext.publishEvent(new ApplicationEvent("本身發佈的事件") {
});
applicationContext.close();
}
// ApplicationListener實現類
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
// 當容器中發佈此事件後,該方法會觸發
public void onApplicationEvent(ApplicationEvent applicationEvent) {
System.out.println("收到的事件:" + applicationEvent);
}
}
// 配置類
@Configuration
@ComponentScan("listener")
public class AppConfig {
}
複製代碼
運行啓動類,輸出結果以下,如下三點說一下:3d
在上面的案例中,收到了三個事件,分別是:ContextRefreshedEvent
、ContextClosedEvent
以及本身定義的MainTest$1[source=本身發佈的事件]
,這幾個事件在底層是如何收到的呢?,咱們就經過源碼來進行分析,在回掉方法onApplicationEvent打上斷點,經過Debug查看源碼:
【1】事件發佈
經過Debug,咱們能夠看到,最早收到ContextRefreshedEvent
事件,下面我們就根據方法調用棧分析ContextRefreshedEvent
如何發佈的
容器建立對象,調用refresh()方法——>finishRefresh()方法——>publishEvent()方法,調用getApplicationEventMulticaster()方法獲取事件的多播器,也就是派發器
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
Object applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent)event;
} else {
applicationEvent = new PayloadApplicationEvent(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
}
}
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
} else {
// 獲取事件的多播器,也就是派發器
this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
}
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext)this.parent).publishEvent(event, eventType);
} else {
this.parent.publishEvent(event);
}
}
}
複製代碼
調用multicastEvent進行事件的派發
public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
Executor executor = this.getTaskExecutor();
Iterator var5 = this.getApplicationListeners(event, type).iterator();
while(var5.hasNext()) {
// 獲取ApplicationListener進行遍歷
ApplicationListener<?> listener = (ApplicationListener)var5.next();
// 判斷是否能夠用executor異步執行,能夠的話使用executor進行異步派發
if (executor != null) {
executor.execute(() -> {
this.invokeListener(listener, event);
});
} else {
// 不然同步執行
this.invokeListener(listener, event);
}
}
}
複製代碼
執行invokeListener方法,拿到listener回調onApplicationEvent方法
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 執行invokeListener方法,拿到listener回調onApplicationEvent方法
listener.onApplicationEvent(event);
} catch (ClassCastException var6) {
String msg = var6.getMessage();
if (msg != null && !this.matchesClassCastMessage(msg, event.getClass())) {
throw var6;
}
Log logger = LogFactory.getLog(this.getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, var6);
}
}
}
複製代碼
【2】獲取事件派發器getApplicationEventMulticaster
容器建立對象,調用refresh()方法——>initApplicationEventMulticaster()方法,初始化ApplicationEventMulticaster
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
// 從bean工廠中找是否有ID爲「applicationEventMulticaster」的組件
if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
// 獲取到該組件
this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
} else {
// 若是沒有則本身建立一個簡單的ApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
// 將建立的註冊到容器的單實例bean中
beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
if (this.logger.isTraceEnabled()) {
this.logger.trace("No 'applicationEventMulticaster' bean, using [" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
複製代碼
【3】容器中有哪些監聽器
容器建立對象,調用refresh()方法——>registerListeners()方法,註冊監聽器
protected void registerListeners() {
// 獲取全部Listener
Iterator var1 = this.getApplicationListeners().iterator();
while(var1.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var1.next();
this.getApplicationEventMulticaster().addApplicationListener(listener);
}
// 從容器中拿到全部ApplicationListener類型的Listener組件
String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
String[] var7 = listenerBeanNames;
int var3 = listenerBeanNames.length;
for(int var4 = 0; var4 < var3; ++var4) {
String listenerBeanName = var7[var4];
// 把組件添加到getApplicationEventMulticaster派發器中,註冊到派發器中
this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
Iterator var9 = earlyEventsToProcess.iterator();
while(var9.hasNext()) {
ApplicationEvent earlyEvent = (ApplicationEvent)var9.next();
this.getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
複製代碼
事件發佈流程: