Spring監(jiān)聽(tīng)器之ApplicationListener原理及源碼深度解析
一、原理及源碼解析
事件:ContextRefreshedEvent、IOCTest_Ext$1[source=我發(fā)布的事件]、ContextClosedEvent;
* 1)、ContextRefreshedEvent事件:
* 1)、容器創(chuàng)建對(duì)象:refresh();
* 2)、finishRefresh();容器刷新完成會(huì)發(fā)布ContextRefreshedEvent事件
* 2)、自己發(fā)布事件;
* 3)、容器關(guān)閉會(huì)發(fā)布ContextClosedEvent;
*
* 【事件發(fā)布流程】源碼執(zhí)行流程:
* 3)、publishEvent(new ContextRefreshedEvent(this));
* 1)、獲取事件的多播器(派發(fā)器):getApplicationEventMulticaster()
* 2)、multicastEvent派發(fā)事件:
* 3)、獲取到所有的ApplicationListener;
* for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
* 1)、如果有Executor,可以支持使用Executor進(jìn)行異步派發(fā);
* Executor executor = getTaskExecutor();
* 2)、否則,同步的方式直接執(zhí)行l(wèi)istener方法;invokeListener(listener, event);
* 拿到listener回調(diào)onApplicationEvent方法;
*
* 【事件多播器(派發(fā)器)】源碼執(zhí)行流程:
* 1)、容器創(chuàng)建對(duì)象:refresh();
* 2)、initApplicationEventMulticaster();初始化ApplicationEventMulticaster;
* 1)、先去容器中找有沒(méi)有id=“applicationEventMulticaster”的組件;
* 2)、如果沒(méi)有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
* 并且加入到容器中,我們就可以在其他組件要派發(fā)事件,自動(dòng)注入這個(gè)applicationEventMulticaster;
*
* 【容器中有哪些監(jiān)聽(tīng)器】源碼執(zhí)行流程:
* 1)、容器創(chuàng)建對(duì)象:refresh();
* 2)、registerListeners();
* 從容器中拿到所有的監(jiān)聽(tīng)器,把他們注冊(cè)到applicationEventMulticaster中;
* String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
* //將listener注冊(cè)到ApplicationEventMulticaster中
* getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
*
* SmartInitializingSingleton 原理:->afterSingletonsInstantiated();
* 1)、ioc容器創(chuàng)建對(duì)象并refresh();
* 2)、finishBeanFactoryInitialization(beanFactory);初始化剩下的單實(shí)例bean;
* 1)、先創(chuàng)建所有的單實(shí)例bean;getBean();
* 2)、獲取所有創(chuàng)建好的單實(shí)例bean,判斷是否是SmartInitializingSingleton類(lèi)型的;
* 如果是就調(diào)用afterSingletonsInstantiated();
*
二、實(shí)例
ApplicationListener:監(jiān)聽(tīng)容器中發(fā)布的事件。事件驅(qū)動(dòng)模型開(kāi)發(fā);
* public interface ApplicationListener<E extends ApplicationEvent>
* 監(jiān)聽(tīng) ApplicationEvent 及其下面的子事件;
*
* 步驟:
* 1)、寫(xiě)一個(gè)監(jiān)聽(tīng)器(ApplicationListener實(shí)現(xiàn)類(lèi))來(lái)監(jiān)聽(tīng)某個(gè)事件(ApplicationEvent及其子類(lèi))
* @EventListener;
* 原理:使用EventListenerMethodProcessor處理器來(lái)解析方法上的@EventListener;
*
* 2)、把監(jiān)聽(tīng)器加入到容器;
* 3)、只要容器中有相關(guān)事件的發(fā)布,我們就能監(jiān)聽(tīng)到這個(gè)事件;
* ContextRefreshedEvent:容器刷新完成(所有bean都完全創(chuàng)建)會(huì)發(fā)布這個(gè)事件;
* ContextClosedEvent:關(guān)閉容器會(huì)發(fā)布這個(gè)事件;
* 4)、發(fā)布一個(gè)事件:
* applicationContext.publishEvent();
1、自定義監(jiān)聽(tīng)器
定義MyApplicationListener 類(lèi)并實(shí)現(xiàn)ApplicationListener<ApplicationEvent>接口
用@Component裝配到Spring容器中
package com.atguigu.ext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
//當(dāng)容器中發(fā)布此事件以后,方法觸發(fā)
@Override
public void onApplicationEvent(ApplicationEvent event) {
// TODO Auto-generated method stub
System.out.println("收到事件:"+event);
}
}或者使用@EventListener注解來(lái)定義一個(gè)監(jiān)聽(tīng)器
注:@EventListener(classes={ApplicationEvent.class})中classes監(jiān)聽(tīng)的類(lèi)可以是多個(gè),以逗號(hào)分開(kāi)
package com.atguigu.ext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@EventListener(classes={ApplicationEvent.class})
public void listen(ApplicationEvent event){
System.out.println("UserService。。監(jiān)聽(tīng)到的事件:"+event);
}
}2、定義配置類(lèi),加載IOC容器
@ComponentScan("com.atguigu.ext")
@Configuration
public class ExtConfig {
@Bean
public Blue blue(){
return new Blue();
}
}3、測(cè)試
自定義發(fā)布事件使用了匿名內(nèi)部類(lèi)
package com.atguigu.test;
import org.junit.Test;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.atguigu.ext.ExtConfig;
public class IOCTest_Ext {
@Test
public void test01(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ExtConfig.class);
//發(fā)布事件;
applicationContext.publishEvent(new ApplicationEvent(new String("我發(fā)布的事件")) {
});
applicationContext.close();
}
}結(jié)果:


說(shuō)明:spring自己有自定義監(jiān)聽(tīng)器,如容器有刷新和關(guān)閉事件發(fā)布就會(huì)被監(jiān)聽(tīng)到;自己定義了監(jiān)聽(tīng)器并裝配到spring容器中,一旦有相關(guān)事件發(fā)布也可以被監(jiān)聽(tīng)到。
到此這篇關(guān)于Spring監(jiān)聽(tīng)器之ApplicationListener原理及源碼深度解析的文章就介紹到這了,更多相關(guān)Spring ApplicationListener原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Spring事件監(jiān)聽(tīng)器ApplicationListener的使用與原理分析
- Spring中ApplicationListener的使用解析
- SpringBoot中的ApplicationListener事件監(jiān)聽(tīng)器使用詳解
- SpringBoot中ApplicationEvent和ApplicationListener用法小結(jié)
- Spring ApplicationListener的使用詳解
- SpringMVC事件監(jiān)聽(tīng)ApplicationListener實(shí)例解析
- Spring ApplicationListener監(jiān)聽(tīng)器用法詳解
- springBoot的事件機(jī)制GenericApplicationListener用法解析
相關(guān)文章
SpringCloud一個(gè)模塊調(diào)用另一個(gè)模塊的服務(wù)實(shí)現(xiàn)過(guò)程
SpringCloud服務(wù)調(diào)用詳解與Hystrix熔斷機(jī)制介紹,通過(guò)創(chuàng)建接口和添加依賴(lài)實(shí)現(xiàn)不同模塊間的服務(wù)調(diào)用,并探討了Hystrix在處理容錯(cuò)和熔斷中的應(yīng)用2026-06-06
java 多態(tài)性詳解及簡(jiǎn)單實(shí)例
這篇文章主要介紹了java 多態(tài)性詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02
Java程序?qū)崿F(xiàn)導(dǎo)出Excel的方法(支持IE低版本)
下面小編就為大家?guī)?lái)一篇Java程序?qū)崿F(xiàn)導(dǎo)出Excel的方法(支持IE低版本)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07
Java List接口與Iterator接口及foreach循環(huán)使用解析
這篇文章主要介紹了Java List接口與Iterator接口及foreach循環(huán),主要包括List接口與Iterator接口及foreach循環(huán)具體的使用方法和代碼,需要的朋友可以參考下2022-04-04
Springboot shiro認(rèn)證授權(quán)實(shí)現(xiàn)原理及實(shí)例
這篇文章主要介紹了Springboot shiro認(rèn)證授權(quán)實(shí)現(xiàn)原理及實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06
jackson 實(shí)現(xiàn)null轉(zhuǎn)0 以及0轉(zhuǎn)null的示例代碼
這篇文章主要介紹了jackson 實(shí)現(xiàn)null轉(zhuǎn)0 以及0轉(zhuǎn)null的示例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09

