SpringBoot源碼 - run方法啟動(dòng)流程

我們從主方法啟動(dòng)的入口開始,如下:

public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
}

run方法主要干了兩件事,一件是創(chuàng)建 SpringApplication 并進(jìn)行初始化,初始化如下圖:

創(chuàng)建SpringApplication對象并初始化.jpg

另一件是run的執(zhí)行,我們重點(diǎn)看run的執(zhí)行流程短荐,一路點(diǎn)擊run方法,直到:

run過程.jpg

這個(gè)就是run方法啟動(dòng)的主流程了叹哭,下面一步步來看:

  • 創(chuàng)建秒表計(jì)時(shí)器忍宋,開始計(jì)時(shí)

    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    
  • 配置Headless屬性

    private void configureHeadlessProperty() {              System.setProperty("java.awt.headless",      System.getProperty("java.awt.headless",    Boolean.toString(this.headless)));
    }
    

    這里同一個(gè)屬性,取了有設(shè)置回去话速,看起來一模一樣讶踪,其實(shí)是因?yàn)?getProperty帶兩個(gè)參數(shù)的時(shí)候,會(huì)給默認(rèn)值泊交,所以再設(shè)置一次就能保證該屬性都有值

  • 從META-INF/spring.factories找到所有SpringApplicationRunListener的監(jiān)聽器乳讥,啟動(dòng)監(jiān)聽器

    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    
  • 配置環(huán)境 ConfigurableEnvironment,加入到監(jiān)聽器對象中

    ConfigurableEnvironment environment = this.prepareEnvironment(listeners,                                                     bootstrapContext, applicationArguments);
    
    

    點(diǎn)擊prepareEnvironment方法進(jìn)去廓俭,方法里首先創(chuàng)建環(huán)境對象:

    ConfigurableEnvironment environment = this.getOrCreateEnvironment();
    

    接著配置環(huán)境:

    this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
    

    而 configureEnvironment()方法云石,會(huì)進(jìn)行以下兩個(gè)操作:

    // 加載配置源參數(shù)和命令行屬性
    this.configurePropertySources(environment, args);
    // 配置當(dāng)前activede的描述文件
    this.configureProfiles(environment, args);
    

    回到prepareEnvironment方法:

prepareEnvironment方法.jpg

準(zhǔn)備系統(tǒng)環(huán)境:

listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);

接下來bindToSpringApplication()方法:

protected void bindToSpringApplication(ConfigurableEnvironment environment) {
        try {
            Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
        } catch (Exception var3) {
            throw new IllegalStateException("Cannot bind to SpringApplication", var3);
        }
    }

將配置文件中的spring.main開頭的配置信息綁定到SpringApplication類對應(yīng)的屬性中。

再回到run主流程中:

prepareEnvironment之后.jpg
  • configureIgnoreBeanInfo
configureIgnoreBeanInfo.jpg

設(shè)置忽略掉的bean

  • 接下來是打印 banner:

    Banner printedBanner = this.printBanner(environment);
    
  • 接著這一步比較重要研乒,就是創(chuàng)建容器:

    context = this.createApplicationContext();
    
  • 接下來是prepareContext方法

prepareContext.jpg

具體如下:

// 將環(huán)境變量設(shè)置到容器中
context.setEnvironment(environment);
// 對 ApplicationContext進(jìn)行后置處理汹忠,設(shè)置beanNameGenerator、resourceLoader、classLoader和conversionService
this.postProcessApplicationContext(context);
// 獲取之前獲取到的所有 initializer 類型的類宽菜,并進(jìn)行初始化
this.applyInitializers(context);
// 通知監(jiān)聽器context準(zhǔn)備完成
listeners.contextPrepared(context);

// 打印profile信息
this.logStartupProfileInfo(context);
   
// 注冊一個(gè)應(yīng)用參數(shù)實(shí)例
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
   beanFactory.registerSingleton("springApplicationArguments", applicationArguments);

// 注冊 printedBanner實(shí)例
beanFactory.registerSingleton("springBootBanner", printedBanner);

// 設(shè)置是否允許同名bean谣膳,默認(rèn)false
((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);

// 獲取,加載啟動(dòng)類铅乡,注入到容器中
Set<Object> sources = this.getAllSources();
this.load(context, sources.toArray(new Object[0]));

//觸發(fā)監(jiān)聽器继谚,調(diào)用每個(gè) SpringApplicationRunListerner 的 contextLoaded 方法
listeners.contextLoaded(context);
  • refreshContext 刷新容器,完成組件的掃描阵幸、創(chuàng)建花履、加載等

    this.refreshContext(context);
    
  • 返回容器

    return context;
    

    總流程圖如下:


    run流程.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市挚赊,隨后出現(xiàn)的幾起案子诡壁,更是在濱河造成了極大的恐慌,老刑警劉巖荠割,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妹卿,死亡現(xiàn)場離奇詭異,居然都是意外死亡蔑鹦,警方通過查閱死者的電腦和手機(jī)纽帖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來举反,“玉大人,你說我怎么就攤上這事扒吁』鸨牵” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵雕崩,是天一觀的道長魁索。 經(jīng)常有香客問我,道長盼铁,這世上最難降的妖魔是什么粗蔚? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮饶火,結(jié)果婚禮上鹏控,老公的妹妹穿的比我還像新娘。我一直安慰自己肤寝,他們只是感情好当辐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鲤看,像睡著了一般缘揪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天找筝,我揣著相機(jī)與錄音蹈垢,去河邊找鬼。 笑死袖裕,一個(gè)胖子當(dāng)著我的面吹牛曹抬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播陆赋,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼沐祷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了攒岛?” 一聲冷哼從身側(cè)響起赖临,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎灾锯,沒想到半個(gè)月后兢榨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顺饮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年吵聪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兼雄。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吟逝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赦肋,到底是詐尸還是另有隱情块攒,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布佃乘,位于F島的核電站囱井,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏趣避。R本人自食惡果不足惜庞呕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望程帕。 院中可真熱鬧住练,春花似錦、人聲如沸愁拭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽敛苇。三九已至妆绞,卻和暖如春顺呕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背括饶。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工株茶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人图焰。 一個(gè)月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓启盛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親技羔。 傳聞我的和親對象是個(gè)殘疾皇子僵闯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349

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