springboot啓動類--SpringApplication.run()詳解

前言

實習的第一個項目是利用springboot完成一個需求,在項目搭建的過程中真正感受到springboot的強大,springboot的起步依賴以及自動配置特性簡直不要太爽,在項目搭建的過程中解放了我們的小手。而springboot的啓動也非常簡單,只需要啓動springboot的啓動類,springboot會幫助我們準備所有的環境,包括server,監聽器,裝配spring的上下文等等,springboot的啓動類如此強大我們沒有理由不去深究一下。

目錄

啓動類

創建SpringApplication對象

調用run方法

總結


啓動類

@SpringBootApplication
public class SpringTestApplication {

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

}

SpringTestApplication類執行main方法,main方法調用SpringApplication的run方法。

run方法幹了兩件事:

  1. 創建SpringApplication對象
  2. 利用創建好的SpringApplication對象調用run方法

創建SpringApplication對象

在執行SpringApplication的run方法時首先會創建一個SpringApplication類的對象,利用構造方法創建SpringApplication對象時會調用initialize方法。

SpringApplication.run()方法的基本調用流程:

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

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

public SpringApplication(Object... sources) {
		initialize(sources);
	}

initialize方法:

private void initialize(Object[] sources) {
    // 在sources不爲空時,保存配置類
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    // 判斷是否爲web應用
    this.webEnvironment = deduceWebEnvironment();
    // 獲取並保存容器初始化類,通常在web應用容器初始化使用
    // 利用loadFactoryNames方法從路徑MEAT-INF/spring.factories中找到所有的ApplicationContextInitializer
    setInitializers((Collection) getSpringFactoriesInstances(
        ApplicationContextInitializer.class));
    // 獲取並保存監聽器
    // 利用loadFactoryNames方法從路徑MEAT-INF/spring.factories中找到所有的ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 從堆棧信息獲取包含main方法的主配置類
    this.mainApplicationClass = deduceMainApplicationClass();
}

調用run方法

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    FailureAnalyzers analyzers = null;
    // 配置屬性
    configureHeadlessProperty();
    // 獲取監聽器
    // 利用loadFactoryNames方法從路徑MEAT-INF/spring.factories中找到所有的SpringApplicationRunListener
    SpringApplicationRunListeners listeners = getRunListeners(args);
    // 啓動監聽
    // 調用每個SpringApplicationRunListener的starting方法
    listeners.starting();
    try {
        // 將參數封裝到ApplicationArguments對象中
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
        // 準備環境
        // 觸發監聽事件——調用每個SpringApplicationRunListener的environmentPrepared方法
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
        // 從環境中取出Banner並打印
        Banner printedBanner = printBanner(environment);
        // 依據是否爲web環境創建web容器或者普通的IOC容器
        context = createApplicationContext();
        analyzers = new FailureAnalyzers(context);
        // 準備上下文
        // 1.將environment保存到容器中
        // 2.觸發監聽事件——調用每個SpringApplicationRunListeners的contextPrepared方法
        // 3.調用ConfigurableListableBeanFactory的registerSingleton方法向容器中注入applicationArguments與printedBanner
        // 4.觸發監聽事件——調用每個SpringApplicationRunListeners的contextLoaded方法
        prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
        // 刷新容器,完成組件的掃描,創建,加載等
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        // 觸發監聽事件——調用每個SpringApplicationRunListener的finished方法
        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);
    }
}

總結

SpringApplication.run一共做了兩件事

  1. 創建SpringApplication對象;在對象初始化時保存事件監聽器,容器初始化類以及判斷是否爲web應用,保存包含main方法的主配置類。
  2. 調用run方法;準備spring的上下文,完成容器的初始化,創建,加載等。會在不同的時機觸發監聽器的不同事件。

參考文獻:

【1】.https://www.cnblogs.com/davidwang456/p/5846513.html

【2】.https://mp.weixin.qq.com/s/O2zS2yyLy1Vu_aPtR28wiQ

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