SpringBoot-啟動原理

Spring Boot應(yīng)用的整個啟動流程都封裝在SpringApplication.run方法中,其整個流程很長,但本質(zhì)上就是在Spring容器啟動的基礎(chǔ)上做了大量的擴展,按照這個思路來看看源碼:

項目啟動是通過SpringApplication的靜態(tài)run方法,那么,這個方法里面首先要創(chuàng)建一個SpringApplication對象實例,然后調(diào)用這個創(chuàng)建好的SpringApplication的實例方法

public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
        return new SpringApplication(sources).run(args);
    }

SpringApplication實例初始化完成并且完成設(shè)置后,就開始執(zhí)行run方法的邏輯了

public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        FailureAnalyzers analyzers = null;
        configureHeadlessProperty();
        // 1通過SpringFactoriesLoader加載所有的SpringApplicationRunListeners,并調(diào)用starting()方法
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        try {
            // 2 創(chuàng)建并配置當(dāng)前應(yīng)用將要使用的Environment配置文件(profile)和屬性(properties)
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
            // 3 SpringBoot應(yīng)用在啟動輸出的Banner 圖
            Banner printedBanner = printBanner(environment);
            // 4 根據(jù)是否是web項目,來創(chuàng)建不同的ApplicationContext容器
            context = createApplicationContext();
            // 5 通過SpringFactoriesLoader創(chuàng)建一系列FailureAnalyzer用于監(jiān)控(實現(xiàn)FailureAnalyzer接口的class)
            analyzers = new FailureAnalyzers(context);
            // 6 初始化ApplicationContext
            prepareContext(context, environment, listeners, applicationArguments,printedBanner);
            // 7 調(diào)用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序
            refreshContext(context);
            // 8 查找當(dāng)前context中是否注冊有CommandLineRunner和ApplicationRunner,如果有則遍歷執(zhí)行它們。
            afterRefresh(context, applicationArguments);
            // 9 執(zhí)行所有SpringApplicationRunListener的finished()方法。
            listeners.finished(context, null);
            stopWatch.stop();
            return context;
        }
        catch (Throwable ex) {
            handleRunFailure(context, listeners, analyzers, ex);
            throw new IllegalStateException(ex);
        }
    }

下面來對于上圖每一步進(jìn)行詳細(xì)的講解

1. 啟動所有SpringApplicationRunListeners

通過SpringFactoriesLoader查找并加載所有的SpringApplicationRunListeners,通過調(diào)用starting()方法通知所有的SpringApplicationRunListeners:應(yīng)用開始啟動了。SpringApplicationRunListeners其本質(zhì)上就是一個事件發(fā)布者,它在SpringBoot應(yīng)用啟動的不同時間點發(fā)布不同應(yīng)用事件類型(ApplicationEvent),如果有哪些事件監(jiān)聽者(ApplicationListener)對這些事件感興趣,則可以接收并且處理。

主要是啟動監(jiān)聽器用來監(jiān)聽后面各個階段的觸發(fā)的事件。源碼如下

public interface SpringApplicationRunListener {
    // 運行run方法時立即調(diào)用此方法,可以用戶非常早期的初始化工作
    void starting();
    // Environment準(zhǔn)備好后,并且ApplicationContext創(chuàng)建之前調(diào)用
    void environmentPrepared(ConfigurableEnvironment environment);
    // ApplicationContext創(chuàng)建好后立即調(diào)用
    void contextPrepared(ConfigurableApplicationContext context);
    // ApplicationContext加載完成,在refresh之前調(diào)用
    void contextLoaded(ConfigurableApplicationContext context);
    // 當(dāng)run方法結(jié)束之前調(diào)用
    void finished(ConfigurableApplicationContext context, Throwable exception);
}

2. 配置Environment

創(chuàng)建并配置當(dāng)前應(yīng)用將要使用的Environment,Environment用于描述應(yīng)用程序當(dāng)前的運行環(huán)境,其抽象了兩個方面的內(nèi)容:配置文件(profile)和屬性(properties),開發(fā)經(jīng)驗豐富的同學(xué)對這兩個東西一定不會陌生:不同的環(huán)境(eg:生產(chǎn)環(huán)境、預(yù)發(fā)布環(huán)境)可以使用不同的配置文件,而屬性則可以從配置文件、環(huán)境變量、命令行參數(shù)等來源獲取。因此,當(dāng)Environment準(zhǔn)備好后,在整個應(yīng)用的任何時候,都可以從Environment中獲取資源。

  • 判斷Environment是否存在,不存在就創(chuàng)建(如果是web項目就創(chuàng)建StandardServletEnvironment,否則創(chuàng)建StandardEnvironment)
  • 配置Environment:配置profile以及properties
  • 調(diào)用SpringApplicationRunListener的environmentPrepared()方法,通知事件監(jiān)聽者:應(yīng)用的Environment已經(jīng)準(zhǔn)備好

3. 輸出Banner圖

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.6.RELEASE)

4. 根據(jù)是否是web項目,來創(chuàng)建不同的ApplicationContext容器

5. 創(chuàng)建一系列FailureAnalyzer

創(chuàng)建流程依然是通過SpringFactoriesLoader獲取到所有實現(xiàn)FailureAnalyzer接口的class,然后在創(chuàng)建對應(yīng)的實例。FailureAnalyzer用于分析故障并提供相關(guān)診斷信息。

6. 初始化ApplicationContext

  • 將準(zhǔn)備好的Environment設(shè)置給ApplicationContext
  • 遍歷調(diào)用所有的ApplicationContextInitializer的initialize()方法來對已經(jīng)創(chuàng)建好的ApplicationContext進(jìn)行進(jìn)一步的處理
  • 調(diào)用SpringApplicationRunListener的contextPrepared()方法,通知所有的監(jiān)聽者:ApplicationContext已經(jīng)準(zhǔn)備完畢
  • 將所有的bean加載到容器中
  • 調(diào)用SpringApplicationRunListener的contextLoaded()方法,通知所有的監(jiān)聽者:ApplicationContext已經(jīng)裝載完畢

7 調(diào)用ApplicationContext的refresh()方法

調(diào)用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序,主要獲取到所有的BeanFactoryPostProcessor來對容器做一些額外的操作。BeanFactoryPostProcessor允許我們在容器實例化相應(yīng)對象之前,對注冊到容器的BeanDefinition所保存的信息做一些額外的操作

// 摘自refresh()方法中一句代碼
invokeBeanFactoryPostProcessors(beanFactory);
// 其實現(xiàn)類
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    ......
}

8.查找當(dāng)前context中是否注冊有CommandLineRunner和ApplicationRunner,如果有則遍歷執(zhí)行它們。

9.執(zhí)行所有SpringApplicationRunListener的finished()方法。

這就是Spring Boot的整個啟動流程,其核心就是在Spring容器初始化并啟動的基礎(chǔ)上加入各種擴展點,這些擴展點包括:ApplicationContextInitializer、ApplicationListener以及各種BeanFactoryPostProcessor等等

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容