SpringBoot學習系列之二:啓動原理分析

引言
我們都知道SpringBoot是目前微服務比較流行的技術選型,它可以將工程打成war包的方式在tomcat進行啓動,也可以打成jar包,直接對外提供服務。那我們就會好奇,它是怎麼去啓動服務的,同時是怎麼去加載前端頁面、js文件、配置文件以及class文件等等然後向外提供web服務的。帶着一系列的疑問,一步步探究SpringBoot的啓動原理。

  • SpringBoot大致啓動流程

  • 源碼跟蹤分析

  • 總結


1.SpringBoot大致啓動流程如下圖所示。

這裏寫圖片描述

2.源碼跟蹤分析

(1)main函數爲主程序入口,SpringApplication調用run方法來啓動SpringBoot服務。註解的含義在上一篇文章中進行了說明,這裏不再贅述。

@SpringBootApplication(scanBasePackages = {"com.hikvision.center"})
@MapperScan("com.hikvision.center.module.mapper")
@ImportResource(locations = {"classpath:springMVC-servlet.xml"})
@ServletComponentScan
public class WebApplication extends SpringBootServletInitializer{
    static Logger logger = LoggerFactory.getLogger(WebApplication.class);
    public static void main(String[] args) {
            //程序入口
            SpringApplication.run(WebApplication.class, args);

    }


}

(2)run方法是一個靜態方法,主要執行一系列的初始化加載操作。

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

(3)ConfigurableApplicationContext表示該 Context 是可修改的,也就是在構建 Context中用戶可以動態添加或修改已有的配置信息。下圖爲ApplicationContext類關係圖。
這裏寫圖片描述

//創建了SpringApplication實例,同時調用run方法
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
    return new SpringApplication(sources).run(args);
}

(4)初始化操作。

//SpringApplication構造函數中,進行初始化操作,上下文從指定的源中加載bean,實例可以在被調用前進行自定義
public SpringApplication(Object... sources) {
        initialize(sources);
    }

(5)主要是爲SpringApplication對象賦一些初值。

@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    //判斷當前允許的環境是否爲web環境
    this.webEnvironment = deduceWebEnvironment();
    //
    setInitializers((Collection) getSpringFactoriesInstances(
            ApplicationContextInitializer.class));
    //
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //
    this.mainApplicationClass = deduceMainApplicationClass();
}

(6)回到run方法中去看具體的實現,該方法主要完成ApplicationContext配置加載。

public ConfigurableApplicationContext run(String... args) {
    //性能檢查,查看代碼的運行時間
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    //設置上下文ID,設置父應用上下文,添加監聽器和刷新容器相關的操作等
    ConfigurableApplicationContext context = null;
    //異常分析器
    FailureAnalyzers analyzers = null;
    //設置java.awt.headless屬性,
    configureHeadlessProperty();
    //創建應用監聽器SpringApplicationRunListeners同時開始監聽
    SpringApplicationRunListeners listeners = getRunListeners(args);
    //啓動監聽器
    listeners.started();
    try {
        //獲取啓動參數
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                args);
        //加下SpringBoot配置環境
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
                applicationArguments);
        //定義輸出的標誌,打印spring
        Banner printedBanner = printBanner(environment);
        //創建應用上下文
        context = createApplicationContext();
        //註冊異常分析器
        analyzers = new FailureAnalyzers(context);
        //爲ApplicationContext加載environment,初始化IoC容器,調用SpringApplicationRunListener的contextLoaded()方法,完成IOC容器加載
        prepareContext(context, environment, listeners, applicationArguments,
                printedBanner);
        //初始化自動配置
        refreshContext(context);
        //SpringBoot完成ApplicationContext初始化
        afterRefresh(context, applicationArguments);
        //廣播已經完成初始化全部過程
        listeners.finished(context, null);
        //關閉任務執行還見監聽器
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                    .logStarted(getApplicationLog(), stopWatch);
        }
        return context;
    }
    catch (Throwable ex) {
        handleRunFailure(context, listeners, analyzers, ex);
        throw new IllegalStateException(ex);
    }
}

3.總結
從以上Springboot啓動過程來看,它主要創建了程序配置環境(environment)、事件監聽(listeners)、應用上下文(applicationContext),並在以上基礎上,在容器中開始加載和實例化我們需要的Bean,在這些過程中有些過程是可以自定義的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章