springboot啟動流程(五)創建ApplicationContext


所有文章

https://www.cnblogs.com/lay2017/p/11478237.html

 

正文

springboot在啟動過程中將會根據當前應用的類型創建對應的ApplicationContext。本文內容較短,承上啟下,將不會涉及太多具體的內容,主要在於為后續的ioc內容構建一個ApplicationContext實例。

我們簡單回顧一下,在第二篇文章介紹SpringApplication的run方法

public ConfigurableApplicationContext run(String... args) {
    // 聲明一個Context容器
    ConfigurableApplicationContext context = null;
    // 獲取監聽器
    SpringApplicationRunListeners listeners = getRunListeners(args);
    // 調用監聽器的啟動
    listeners.starting();

    try {
        // 創建並配置Environment(這個過程會加載application配置文件)
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        // 根據應用類型創建對應的Context容器
        context = createApplicationContext();

        // 刷新Context容器之前的准備
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        // 刷新Context容器
        refreshContext(context);
        // 刷新Context容器之后處理
        afterRefresh(context, applicationArguments);

        // Context容器refresh完畢發布
        listeners.started(context);

        // 觸發Context容器refresh完以后的執行
        callRunners(context, applicationArguments);
    } catch (Throwable ex) {}

    try {
        // Context啟動完畢,Runner運行完畢發布
        listeners.running(context);
    } catch (Throwable ex) {}

    return context;
}

邏輯步驟中,創建Environment之后,刷新ApplicationContext之前,我們還需要做的一件事就是創建ApplicationContext實例,也就是createApplicationContext方法

 

我們跟進createApplicationContext

public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext";

public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";

public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context.annotation.AnnotationConfigApplicationContext";

protected ConfigurableApplicationContext createApplicationContext() {
    // 先判斷有沒有指定的實現類
    Class<?> contextClass = this.applicationContextClass;
    // 如果沒有,則根據應用類型選擇
    if (contextClass == null) {
        try {
            switch (this.webApplicationType) {
            case SERVLET: 
                contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
                break;
            case REACTIVE:
                contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                break;
            default:
                contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
            }
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                    "Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
                    ex);
        }
    }
    // 通過反射獲取對應類的實例
    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

該方法的邏輯較為簡單,走兩個分支

1)自定義ApplicationContext的實現類

2)根據當前應用的類型webApplicationType來匹配對應的ApplicationContext,是servlet、reactive或者非web應用

 

總結

創建ApplicationContext的實例對象較為簡單,就是選擇實現類,反射獲取類的實例對象。至於實現類是自己設置的,還是通過當前應用類型匹配的由開發人員去選擇,不過默認情況下都是由類型去推斷出來的。

本文雖短,但是后續的文章也基本都是圍繞着本文構建的ApplicationContext,這說明spring的核心也基本都包含在這個ApplicationContext當中了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM