這篇文章給大家介紹springboot2.0.6如何啟動(dòng)監(jiān)聽(tīng)器,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
創(chuàng)新互聯(lián)建站堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都做網(wǎng)站、網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿(mǎn)足客戶(hù)于互聯(lián)網(wǎng)時(shí)代的楚雄州網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
public ConfigurableApplicationContext run(String... args) { ......//省略 // 獲取一個(gè)run監(jiān)聽(tīng)器,主要監(jiān)聽(tīng)SpringApplication對(duì)象,(內(nèi)部只有一個(gè)EventPublishingRunListener) SpringApplicationRunListeners listeners = getRunListeners(args); //調(diào)用監(jiān)聽(tīng)器的啟動(dòng),當(dāng)SpringApplication對(duì)象的run方法剛啟動(dòng)的時(shí)候(依靠SimpleApplicationEventMulticaster) listeners.starting(); ......//省略 }
SpringApplicationRunListeners 是一個(gè)集合類(lèi),內(nèi)部包含一個(gè) log 和包含 SpringApplicationRunListener 的 List。而 SpringApplicationRunListener 主要是監(jiān)聽(tīng) SpringApplication 對(duì)象的,里面的方法都定義了在何時(shí)調(diào)用 SpringApplicationRunListener 的各種方法。
下面的每一個(gè)方法 SpringApplicationRunListener 都把其包裝成一個(gè)事件,在spring容器還未成功 refreshed 之前都是使用SimpleApplicationEventMulticaster 去尋找對(duì)該事件感興趣的ApplicationListener,然后調(diào)用其onApplicationEvent方法
starting:當(dāng)SpringApplication對(duì)象的run方法剛啟動(dòng)的時(shí)候(依靠SimpleApplicationEventMulticaster)
environmentPrepared:在environment Prepared 但是spring容器還未創(chuàng)建的時(shí)候(依靠SimpleApplicationEventMulticaster)
contextPrepared:當(dāng)spring容器已經(jīng)創(chuàng)建且準(zhǔn)備好了,(目前是空的實(shí)現(xiàn))
contextLoaded:當(dāng)spring容器已經(jīng)loaded 且未refresh 。load就是將我們的primaryClass注冊(cè)到spring容器中,(依靠SimpleApplicationEventMulticaster) 同時(shí)將之前獲取到的ApplicationListener都加入到spring容器中,此時(shí)如果ApplicationListener還是ApplicationContextAware的也要調(diào)用其setApplicationContext方法。
started:spring容器已經(jīng)刷新過(guò)且應(yīng)用已經(jīng)啟動(dòng),但是CommandLineRunners和ApplicationRunners還未調(diào)用,直接通過(guò)spring容器自己發(fā)送(因?yàn)锳pplicationListener已經(jīng)加入spring容器)
running:我們已經(jīng)調(diào)用了CommandLineRunners,直接通過(guò)spring容器自己發(fā)送(因?yàn)锳pplicationListener已經(jīng)加入spring容器)
failed:當(dāng)異常發(fā)生的時(shí)候就調(diào)用這個(gè),如果spring容器沒(méi)有l(wèi)oaded 或者沒(méi)有激活就使用SimpleApplicationEventMulticaster,否則還是依靠spring容器自己
public class SpringApplication { // 獲取監(jiān)聽(tīng) private SpringApplicationRunListeners getRunListeners(String[] args) { // 定義class數(shù)組 Class>[] types = new Class>[] { SpringApplication.class, String[].class }; // 創(chuàng)建SpringApplicationRunListeners對(duì)象 return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args)); } }
默認(rèn)情況下,getRunListeners 方法從 spring.factories 文件中找出key為 SpringApplicationRunListener 的類(lèi)有:
org.springframework.boot.context.event.EventPublishingRunListener
這里我們看到了一個(gè)熟悉的方法getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),前面的博文我們已經(jīng)詳細(xì)介紹過(guò)該方法是怎么一步步的獲取到META-INF/spring.factories中的指定的key的value,獲取到以后怎么實(shí)例化類(lèi)的(參考)。執(zhí)行 獲取的值如下圖
從上圖debug結(jié)果,我們可以看到我們獲取到了一個(gè)監(jiān)聽(tīng)器EventPublishingRunListener,該監(jiān)聽(tīng)器是Spring容器的啟動(dòng)監(jiān)聽(tīng)器。listeners.starting()方法開(kāi)啟了監(jiān)聽(tīng)事件
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered { private final SpringApplication application; private final String[] args; private final SimpleApplicationEventMulticaster initialMulticaster; // 加載監(jiān)聽(tīng)器類(lèi) public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; this.initialMulticaster = new SimpleApplicationEventMulticaster(); // 給initialMulticaster 添加listener for (ApplicationListener> listener : application.getListeners()) { this.initialMulticaster.addApplicationListener(listener); } } // 實(shí)現(xiàn)類(lèi)調(diào)用EventPublishingRunListener的方法 public void starting() { this.initialMulticaster.multicastEvent( // 創(chuàng)建了一個(gè)ApplicationStartingEvent事件,將springapplication的this.application傳入,因此監(jiān)聽(tīng)的時(shí)候獲取的是SpringApplication實(shí)例 new ApplicationStartingEvent(this.application, this.args)); } ......//省略 }
EventPublishingRunListener的初始化方法中 對(duì)application、args進(jìn)行了賦值,并對(duì)SimpleApplicationEventMulticaster進(jìn)行了初始化,然后獲取application中的監(jiān)聽(tīng)器添加給SimpleApplicationEventMulticaster對(duì)象。
進(jìn)入SimpleApplicationEventMulticaster類(lèi)的初始化方法,如下
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster { private Executor taskExecutor; private ErrorHandler errorHandler; public void multicastEvent(ApplicationEvent event) { multicastEvent(event, resolveDefaultEventType(event)); } public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); // 注意getApplicationListeners獲取對(duì)應(yīng)的事件監(jiān)聽(tīng)器 for (final ApplicationListener> listener : getApplicationListeners(event, type)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } } }
SimpleApplicationEventMulticaster類(lèi)繼承 AbstractApplicationEventMulticaster
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware { protected Collection> getApplicationListeners( ApplicationEvent event, ResolvableType eventType) { Object source = event.getSource(); Class> sourceType = (source != null ? source.getClass() : null); ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); // Quick check for existing entry on ConcurrentHashMap… // 快速檢測(cè) COncurrentHashMap 的現(xiàn)有條目 ListenerRetriever retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } if (this.beanClassLoader == null || (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) { // Fully synchronized building and caching of a ListenerRetriever synchronized (this.retrievalMutex) { retriever = this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } retriever = new ListenerRetriever(true); Collection > listeners = retrieveApplicationListeners(eventType, sourceType, retriever); this.retrieverCache.put(cacheKey, retriever); return listeners; } } else { // No ListenerRetriever caching -> no synchronization necessary return retrieveApplicationListeners(eventType, sourceType, null); } } // 實(shí)際上檢索給定事件和源類(lèi)型的應(yīng)用程序監(jiān)聽(tīng)器是否匹配 private Collection > retrieveApplicationListeners( ResolvableType eventType, @Nullable Class> sourceType, @Nullable ListenerRetriever retriever) { List > allListeners = new ArrayList<>(); Set > listeners; Set listenerBeans; synchronized (this.retrievalMutex) { // 這個(gè)listener集合就是前文提到的從配置中過(guò)濾的10個(gè)監(jiān)聽(tīng)器(圖1) listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners); listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans); } // 循環(huán)10個(gè)listener調(diào)用supportsEvent方法 for (ApplicationListener> listener : listeners) { if (supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { retriever.applicationListeners.add(listener); } allListeners.add(listener); } } ......//省略 AnnotationAwareOrderComparator.sort(allListeners); if (retriever != null && retriever.applicationListenerBeans.isEmpty()) { retriever.applicationListeners.clear(); retriever.applicationListeners.addAll(allListeners); } return allListeners; } protected boolean supportsEvent( ApplicationListener> listener, ResolvableType eventType, @Nullable Class> sourceType) { GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ? (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener)); return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType)); } }
-->程序啟動(dòng)
-->調(diào)用getRunListeners(args)獲取SpringApplicationRunListeners實(shí)例
-->getSpringFactoriesInstances()獲取Spring工廠實(shí)例集合
-->loadFactoryNames()通過(guò)classLoader加載/META-INF/spring.factories文件,獲取指定class對(duì)應(yīng)的類(lèi)全限定名稱(chēng)集合
-->loadSpringFactories() 通過(guò)classLoader循環(huán)加載/META-INF/spring.factories文件,獲取文件中類(lèi)全限定名稱(chēng)集合返回
-->createSpringFactoriesInstances()根據(jù)加載文件返回的類(lèi)全限定名稱(chēng)集合創(chuàng)建工廠實(shí)例,反射
-->listeners.starting()啟動(dòng)監(jiān)聽(tīng)器
-->multicastEvent(ApplicationEvent event)組播ApplicationEvent事件
-->getApplicationListeners()判斷監(jiān)聽(tīng)器類(lèi)型是否與當(dāng)前監(jiān)聽(tīng)器類(lèi)型相同
-->retrieveApplicationListeners(eventType, sourceType, retriever)檢索給定事件和源類(lèi)型的應(yīng)用程序監(jiān)聽(tīng)器。
-->supportsEvent(listener, eventType, sourceType)確認(rèn)給定的監(jiān)聽(tīng)器是否支持給定的事件。
-->GenericApplicationListenerAdapter(ApplicationListener> delegate)為給定的委托創(chuàng)建一個(gè)新的GenericApplicationListener。
-->resolveDeclaredEventType(ApplicationListener
-->supportsEventType(eventType)從指定類(lèi)型解析事件
-->結(jié)束
SpringApplicationRunListener的那些方法底層還是依靠spring容器去發(fā)布事件
底層還是會(huì)被ApplicationListener給監(jiān)聽(tīng)到
在spring容器prepareContext調(diào)用之后會(huì)將ApplicationListener都加入到SimpleApplicationEventMulticaster,在這之后所有的事件都會(huì)lazy發(fā)送,即先存在earlyApplicationEvents。等到spring容器refresh之后注冊(cè)所有ApplicationListener,然后在統(tǒng)一發(fā)送之前存儲(chǔ)的事件。
關(guān)于springboot2.0.6如何啟動(dòng)監(jiān)聽(tīng)器就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。