spring boot 啟動(dòng)源碼閱讀(二)

上一篇www.reibang.com/p/a2d575fb52f5中我們閱讀完了構(gòu)造方法所做的一些的事情。接下來(lái)就是SpringApplication中的run方法力九,いくぞ!邑闺!跌前。直接上源碼截圖:

run方法

看著也不是太長(zhǎng),我們先看返回類型陡舅,ConfigurableApplicationContext ?這是一個(gè)interface舒萎,單從名字直譯成可配置的應(yīng)用上下文,對(duì)spring了解的人肯定知道ApplicationContext蹭沛,所以猜測(cè)估計(jì)是跟ApplicationContext有關(guān)系。我們看下此接口的父類關(guān)系圖:


ConfigurableApplicationContext

繼承了一個(gè)Closeable 接口章鲤,一個(gè)Lifecyle 生命周期接口摊灭,還有一個(gè)ApplicationContext接口,我們注意看ApplicationContext主要繼承了BeanFactory和ResourceLoader的一些列子接口败徊,加上一個(gè)ApplicationEventPublisher(事件發(fā)布)帚呼。也就是說(shuō)ConfigurableApplicationContext具有資源加載,事件發(fā)布皱蹦,IOC容器等功能煤杀。


然后我們看run的方法體。StopWatch類里面沒(méi)什么東西沪哺,就是記錄一些運(yùn)行時(shí)間沈自,運(yùn)行的狀態(tài)記錄等,接著往下走辜妓。

1.this.configureHeadlessProperty() 設(shè)置是否是headless模式(java se的系統(tǒng)的一種設(shè)置模式枯途,我也不清楚,具體請(qǐng)搜索)籍滴,上一遍中構(gòu)造函數(shù)初始化的其中一個(gè)成員變量headless在這里起到作用酪夷。

2.SpringApplicationRunListeners listeners =this.getRunListeners(args);? 這個(gè)方法getRunListeners(args)跟構(gòu)造函數(shù)的中的setInitializers和setListeners方法類似,會(huì)在spring.factories文件中尋找SpringApplicationRunListener對(duì)應(yīng)的實(shí)現(xiàn)類的名字孽惰,并且利用反射構(gòu)造實(shí)例晚岭,


圖1

最終得到SpringApplicationRunListener接口的實(shí)現(xiàn)類EventPublishingRunListener的對(duì)象,并且該對(duì)象持有SpringApplication的引用勋功,把EventPublishingRunListener對(duì)象實(shí)例放到SpringApplicationRunListeners這個(gè)容器里面坦报,由SpringApplicationRunListeners對(duì)象來(lái)管理(其實(shí)就是一個(gè)ArrayList來(lái)存放,里面就一個(gè)EventPublishingRunListener實(shí)例)SpringApplicationRunListener的對(duì)象库说。

3.listeners.starting();spring正在啟動(dòng), 此方法會(huì)遍歷listeners容器(ArrayList)里面所有的SpringApplicationRunListener對(duì)象的starting方法燎竖,其實(shí)就是調(diào)用EventPublishingRunListener的starting()璃弄。關(guān)鍵的地方來(lái)了,請(qǐng)看好:


圖2

我們看到starting的實(shí)現(xiàn)构回,里面有個(gè)SimpleApplicationEventMulticaster夏块,這個(gè)對(duì)象就是負(fù)責(zé)廣播ApplicationEvent事件,那么既然是廣播事件纤掸,我們需要知道幾件事情:1.聽(tīng)眾是誰(shuí) 2.什么事件 3聽(tīng)眾如何接收.4接受到如何處理脐供。我點(diǎn)開(kāi)SimpleApplicationEventMulticaster的源碼


SimpleApplicationEventMulticaster

? ? 1.事件是什么,事件就是ApplicationStartedEvent(繼承ApplicationEvent)借跪。從類名上可以看出其實(shí)就是發(fā)出了一個(gè)應(yīng)用開(kāi)始啟動(dòng)的信號(hào)了政己。

? ? 2. 聽(tīng)眾呢?開(kāi)始我以為 聽(tīng)眾就是SpringApplication里的所有的ApplicationListener對(duì)象掏愁,這些對(duì)象 我們?cè)谏弦黄械弥猄pringApplication的構(gòu)造函數(shù)中已經(jīng)初始化好了歇由。但是請(qǐng)看SimpleApplicationEventMulticaster里面的第二個(gè)multicastEvent方法 會(huì)調(diào)用getApplciationListeners,這個(gè)方法會(huì)對(duì)? ? SpringApplication? 所持有的所有ApplicationListener對(duì)象做一個(gè)過(guò)濾果港,過(guò)濾那些能處理ApplicationStartedEvent事件的監(jiān)聽(tīng)器沦泌,也就是說(shuō)不是所有的ApplicationListener都對(duì)這個(gè)事件感興趣或者說(shuō)能處理改事件。最終有5個(gè)listener對(duì)該事件感興趣辛掠。


處理ApplicationStartedEvent事件的ApplicationListener

? ? 3.接下來(lái)就是事件的處理了谢谦,我們從SimpleApplicationEventMulticaster可以得出其實(shí)就是ApplicationListener的onApplication的方法處理接受到的event。那么這5個(gè)類如何處理萝衩,其實(shí)可以通過(guò)類名去猜測(cè)出一些東西回挽,具體先留著后面去一個(gè)一個(gè)去解析。

稍微梳理一下就是 SpringApplicationRunListeners 這個(gè)對(duì)象是SpringApplicationRunListener對(duì)象集合的代理猩谊,整個(gè)應(yīng)用的生命周期會(huì)觸發(fā)SpringApplicationRunListeners里面的各個(gè)狀態(tài)方法(starting,environmentPrepared,contextPrepared,contextLoaded,finished)千劈,換種說(shuō)法就是監(jiān)聽(tīng)著spring的各個(gè)生命周期。比如剛剛說(shuō)的應(yīng)用的starting狀態(tài)牌捷,SpringApplicationRunListeners會(huì)讓集合中的所有SpringApplicationRunListener對(duì)象的starting方去處理(在本例中队塘,集合中只有一個(gè)對(duì)象 就是EventPublishingRunListener)。EventPublishingRunListener的處理方式就是讓SpringApplication的的ApplicationListener的一些列相應(yīng)對(duì)象去處理宜鸯,具體就是通過(guò)SimpleApplicationEventMulticaster來(lái)廣播各種事件給ApplicationListener憔古。也就是說(shuō)整個(gè)應(yīng)用的幾個(gè)狀態(tài)或者說(shuō)生命周期(啟動(dòng)狀態(tài),環(huán)境準(zhǔn)備狀態(tài)淋袖,上下文準(zhǔn)備狀態(tài)鸿市,上下文加載狀態(tài),結(jié)束狀態(tài)),都會(huì)通知相應(yīng)的ApplicationListener對(duì)象焰情,然后ApplicationListener對(duì)象去做該做的事情陌凳。


EventPublishingRunListener



回到文章的開(kāi)頭,run方法接下來(lái)該走到try塊里面了

先看DefaultApplicationArguments ex =new DefaultApplicationArguments(args);將傳經(jīng)來(lái)的參數(shù)args( 本例中其實(shí)就是一段字符串“--debug”内舟,因?yàn)槲沂莇ebug運(yùn)行的)進(jìn)行包裝了一下合敦。

然后ConfigurableEnvironment environment =this.prepareEnvironment(listeners,ex);


prepareEnvironment

主要?jiǎng)?chuàng)建了WEB環(huán)境的上下文,一個(gè)StandardEnvironment验游;方法this.configureEnvironment(environment,applicationArguments.getSourceArgs());配置好系統(tǒng)運(yùn)行的所需要的環(huán)境充岛,里面包含一些配置信息。接著是listeners.environmentPrepared(environment);跟上面的starting方法很像耕蝉,發(fā)出了一個(gè)ApplicationEnvironmentPreparedEvent事件崔梗,廣播給能處理該事件的listener,主要由以下這些:


處理ApplicationEnvironmentPreparedEvent事件的listener

再次回到run方法:

1.Banner printedBanner =this.printBanner(environment);會(huì)在控制臺(tái)打印spring boot項(xiàng)目啟動(dòng)時(shí)候的圖像等事情垒在。就是下面這貨


2.接下來(lái)是context =this.createApplicationContext();因?yàn)槌蓡T變量webEnvironment為false會(huì)創(chuàng)建一個(gè)AnnotationConfigApplicationContext對(duì)象蒜魄,也是run方法返回的對(duì)象。

3.newFailureAnalyzers(context);實(shí)例化一堆錯(cuò)誤分析器场躯,項(xiàng)目啟動(dòng)報(bào)錯(cuò)了告訴你錯(cuò)誤原因谈为,實(shí)例化的過(guò)程跟前面實(shí)例化listener一模一樣,都是套路踢关。b( ̄▽ ̄)b

4.this.prepareContext(context,environment,listeners,ex,printedBanner);這一步做了很多事情峦阁,先簡(jiǎn)要的說(shuō)下

prepareContext


1) 設(shè)置environment到context中;2)設(shè)置context到ApplicationContextInitializer中耘成;3)廣播一個(gè)contextPrepare事件;4)發(fā)起一個(gè)contextLoad事件

5.最后是一個(gè)contextFinish事件驹闰。

總結(jié):spring從啟動(dòng)到啟動(dòng)結(jié)束中瘪菌,各個(gè)生命周期廣播相應(yīng)的事件出去,然后各個(gè)監(jiān)聽(tīng)器收到廣播消息之后去做對(duì)應(yīng)的事情嘹朗。下面畫的這張圖算是自己的初步理解


spring boot啟動(dòng)的生命周期


但是第一篇中遺留的問(wèn)題這篇文章并沒(méi)有解釋师妙。。屹培。留待以后吧默穴!



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市褪秀,隨后出現(xiàn)的幾起案子蓄诽,更是在濱河造成了極大的恐慌,老刑警劉巖媒吗,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仑氛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)锯岖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門介袜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人出吹,你說(shuō)我怎么就攤上這事遇伞。” “怎么了捶牢?”我有些...
    開(kāi)封第一講書人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵鸠珠,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我叫确,道長(zhǎng)跳芳,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任竹勉,我火速辦了婚禮飞盆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘次乓。我一直安慰自己吓歇,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布票腰。 她就那樣靜靜地躺著城看,像睡著了一般。 火紅的嫁衣襯著肌膚如雪杏慰。 梳的紋絲不亂的頭發(fā)上测柠,一...
    開(kāi)封第一講書人閱讀 52,337評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音缘滥,去河邊找鬼轰胁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛朝扼,可吹牛的內(nèi)容都是我干的赃阀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼擎颖,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼榛斯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起搂捧,我...
    開(kāi)封第一講書人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤驮俗,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后允跑,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體意述,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了荤崇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拌屏。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖术荤,靈堂內(nèi)的尸體忽然破棺而出倚喂,到底是詐尸還是另有隱情,我是刑警寧澤瓣戚,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布端圈,位于F島的核電站,受9級(jí)特大地震影響子库,放射性物質(zhì)發(fā)生泄漏舱权。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一仑嗅、第九天 我趴在偏房一處隱蔽的房頂上張望宴倍。 院中可真熱鬧,春花似錦仓技、人聲如沸鸵贬。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)阔逼。三九已至,卻和暖如春地沮,著一層夾襖步出監(jiān)牢的瞬間嗜浮,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工摩疑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留危融,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓未荒,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親及志。 傳聞我的和親對(duì)象是個(gè)殘疾皇子片排,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)速侈,斷路器率寡,智...
    卡卡羅2017閱讀 134,702評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,859評(píng)論 6 342
  • 日子沒(méi)到的時(shí)候就接到四姨打來(lái)邀請(qǐng)的電話,說(shuō)是佛誕日倚搬,讓我要和嫂子們一起去冶共,我說(shuō)嗯,大嫂去的話我也一起去捅僵,四姨說(shuō)家卖,大...
    九憶之城閱讀 208評(píng)論 0 0
  • 服務(wù)組件的規(guī)劃 機(jī)器的配置需要根據(jù)實(shí)際情況考慮。由于我用的虛擬機(jī)庙楚,所以各個(gè)容量大小設(shè)置的都很低上荡。* 注意:搭建分布...
    心_的方向閱讀 931評(píng)論 0 2