Spring中的refreshContext源碼分析
前言
在SpringBoot啟動(dòng)流程中,主要的兩個(gè)階段是初始化SpringApplication對(duì)象以及SpringApplication.run方法執(zhí)行的內(nèi)容
今天主要細(xì)講的是SpringApplication.run中的刷新容器refreshContext方法
refreshContext()
還是老辦法,先梳理它的大體流程,將不太重要的舍去。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
...
// Prepare the bean factory for use in this context.
//設(shè)置beanFacotry 和加載一些特殊bean的處理類,
prepareBeanFactory(beanFactory);
// 一些web項(xiàng)目的bean處理類
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//重要,喚醒 BeanFactoryPostProcessor的實(shí)現(xiàn)類
invokeBeanFactoryPostProcessors(beanFactory);
...
// Register bean processors that intercept bean creation.
//重要,將BeanPostProcessor的bean定義注冊(cè)進(jìn)來
registerBeanPostProcessors(beanFactory);
...
// Initialize event multicaster for this context.
//再次創(chuàng)建一個(gè)廣播器
initApplicationEventMulticaster();
...
// Check for listener beans and register them.
//注冊(cè)listener到上述的心廣播器中
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//重要,創(chuàng)建單例bean
finishBeanFactoryInitialization(beanFactory);
...
}
}那么整體上就分為一下幾步
- 對(duì)beanFacotry進(jìn)行設(shè)置
- 對(duì)benFactory在做一些定制處理(比如加載一些web容器對(duì)bean的處理類)
- 喚醒beanFactoryPostProcessor的一些列實(shí)現(xiàn)類
- 創(chuàng)建一個(gè)新廣播器
- 將Listener加入到這個(gè)新廣播器中(注意,這的Listener將會(huì)比我們上一篇所說的多的多,至于原因 在喚醒那一步里面)
- 將所有找到的單例類,都創(chuàng)建處理(這步內(nèi)容也比較多,對(duì)于加載Bean的分析 將新啟一篇文章進(jìn)行說明)
prepareBeanFactory()
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//添加了一個(gè)BeanPostProcessor實(shí)例ApplicationContextAwareProcessor
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
//指定特定依賴的返回結(jié)果
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
//添加了一個(gè)BeanPostProcessor實(shí)例ApplicationListenerDetector
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
...
}老辦法 ,逐一分析。
第一步,添加了一個(gè)BeanPostProcessor實(shí)例ApplicationContextAwareProcessor
ApplicationContextAwareProcessor //這個(gè)bean處理器就是在實(shí)現(xiàn)了 EnvironmentAware.class EmbeddedValueResolverAware.class ResourceLoaderAware.class ApplicationEventPublisherAware.class MessageSourceAware.class ApplicationContextAware.class //的類實(shí)例化之前喚醒對(duì)應(yīng)的接口方法
指定特定依賴的返回結(jié)果添加了一個(gè)BeanPostProcessor實(shí)例ApplicationListenerDetector
這個(gè)實(shí)例主要是檢查bean是否實(shí)現(xiàn)了ApplicationListener,如果實(shí)現(xiàn)了就將它添加到監(jiān)聽器集合中
前面我們說了也可以通過spring.factories這個(gè)文件添加ApplicationListenr
這里又提供了一種方式,但是這種通過ApplicationListenerDetector來加載的方式 會(huì)讓listener丟失一部分事件(因?yàn)樵跊]有加載Bean之前還有很多事件),如果需要監(jiān)聽非常前面的事件,還是要通過spring.factories這個(gè)文件添加
這里都是講處理類加載進(jìn)來,并沒有執(zhí)行對(duì)應(yīng)方法。真正訪問還在后面,前面只是準(zhǔn)備階段
invokeBeanFactoryPostProcessors()
喚醒所有的BeanFactoryPostProcessor實(shí)例 ,這個(gè)與下面的registerBeanPostProcessor將會(huì)以獨(dú)立的章節(jié)來分析(原因還是那個(gè)原因。。。 里面的內(nèi)容有點(diǎn)多)。
registerBeanPostProcessor()
將BeanPostProcessor實(shí)例注冊(cè)進(jìn)來
registerListeners()
protected void registerListeners() {
// Register statically specified listeners first
//加載老的listener
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
//加載新的listenner
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
//發(fā)送默認(rèn)的事件集
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}這一步就是將listener注冊(cè)到新的廣播器中,分步走。
- 加載老的listener,也就是我們最開始通過spring.factories加載進(jìn)來的監(jiān)聽器
- 加載通過ApplicationListenerDetector注冊(cè)進(jìn)來的監(jiān)聽器
- 發(fā)送默認(rèn)事件(就是表明這個(gè)時(shí)間節(jié)點(diǎn)的事件)到監(jiān)聽器中
完成bean的初始化,這個(gè)會(huì)單獨(dú)形成一個(gè)章節(jié),與getBean流程一起講解
總結(jié)
- 準(zhǔn)備BeanFacotry
- BeanFacotry準(zhǔn)備完畢
- 對(duì)BeanFacotryPostProcessor進(jìn)行喚醒(因?yàn)锽eanFactory準(zhǔn)備完畢了嘛)
- 注冊(cè)BeanPostProcessor(因?yàn)榻酉聛砦覀円獙?shí)例化Bean嘛)
- 對(duì)單例Bean進(jìn)行實(shí)例化
你看,邏輯清晰,前后有因果,一下就把整體流程給理順了,而且出乎意料的合理。
到此這篇關(guān)于Spring中的refreshContext源碼分析的文章就介紹到這了,更多相關(guān)refreshContext源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot插件spring tool suite安裝及使用詳解
這篇文章主要介紹了Spring Boot插件spring tool suite安裝及使用詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
ES結(jié)合java代碼聚合查詢?cè)敿?xì)示例
es查詢有一個(gè)很常用的一種叫聚合查詢,相當(dāng)于mysql中的分組group by 后拿各組數(shù)量進(jìn)行統(tǒng)計(jì),實(shí)現(xiàn)起來也是很簡(jiǎn)單,下面這篇文章主要給大家介紹了關(guān)于ES結(jié)合java代碼聚合查詢的相關(guān)資料,需要的朋友可以參考下2023-05-05
springboot+mybatis plus實(shí)現(xiàn)樹形結(jié)構(gòu)查詢
實(shí)際開發(fā)過程中經(jīng)常需要查詢節(jié)點(diǎn)樹,根據(jù)指定節(jié)點(diǎn)獲取子節(jié)點(diǎn)列表,本文主要介紹了springboot+mybatis plus實(shí)現(xiàn)樹形結(jié)構(gòu)查詢,感興趣的可以了解一下2021-07-07

