springboot啟動(dòng)流程源碼分析

啟動(dòng)分為兩部分,先創(chuàng)建Application然后調(diào)用實(shí)例的run方法。


1、new Application執(zhí)行流程

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {

? ? ? ? this.sources = new LinkedHashSet();

? ? ? ? this.bannerMode = Mode.CONSOLE;

? ? ? ? this.logStartupInfo = true;

? ? ? ? this.addCommandLineProperties = true;

? ? ? ? this.addConversionService = true;

? ? ? ? this.headless = true;

? ? ? ? this.registerShutdownHook = true;

? ? ? ? this.additionalProfiles = new HashSet();

? ? ? ? this.isCustomEnvironment = false;

? ? ? ? this.lazyInitialization = false;

? ? ? ? this.resourceLoader = resourceLoader;

? ? ? ? Assert.notNull(primarySources, "PrimarySources must not be null");

? ? ? ? //保存主配置類

? ? ? ? this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));

? ? ? ? //判斷應(yīng)用是否是web應(yīng)用環(huán)境

? ? ? ? this.webApplicationType = WebApplicationType.deduceFromClasspath();

? ? ? ? //從類路徑下META-INF的spring.factoris文件里找到所有的ApplicationContextInitializer,然后保存起來(lái)

? ? ? ? this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));

? ? ? ? //從類路徑下的META-INF下的spring.factories下找到所有的ApplicationListener類,保存起來(lái)

? ? ? ? this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

? ? ? ? //從幾個(gè)配置類當(dāng)中找到主配置類

? ? ? ? this.mainApplicationClass = this.deduceMainApplicationClass();

? ? }


2.SpringApplication.run(args)流程

public ConfigurableApplicationContext run(String... args) {

? ? ? ? StopWatch stopWatch = new StopWatch();

? ? ? ? stopWatch.start();

? ? ? ? ConfigurableApplicationContext context = null;

? ? ? ? Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();

? ? ? ? this.configureHeadlessProperty();

? ? ? ? //獲取SpringApplicationRunListeners,從類路徑META-INF的spring.factories找所有的SpringApplicationRunListener

? ? ? ? SpringApplicationRunListeners listeners = this.getRunListeners(args);

? ? ? ? //遍歷所有的SpringApplicationRunListener的start()方法

? ? ? ? listeners.starting();

? ? ? ? Collection exceptionReporters;

? ? ? ? try {

? ? ? ? ? ? //封裝命令行參數(shù)

? ? ? ? ? ? ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

? ? ? ? ? ? //準(zhǔn)備環(huán)境,創(chuàng)建完環(huán)境之后調(diào)用SpringApplicationRunListener的environmentPrepared方法,表示環(huán)境準(zhǔn)備完成

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

? ? ? ? ? ? this.configureIgnoreBeanInfo(environment);

? ? ? ? ? ? //控制臺(tái)打印banner圖標(biāo)

? ? ? ? ? ? Banner printedBanner = this.printBanner(environment);

? ? ? ? ? ? //創(chuàng)建ApplicationContext,決定創(chuàng)建web的ioc容器還是普通的ioc容器

? ? ? ? ? ? context = this.createApplicationContext();

? ? ? ? ? ? exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);


? ? ? ? ? ? //準(zhǔn)備上下文環(huán)境 將environment保存到ioc容器當(dāng)中,而且applyInitializers();

? ? ? ? ? ? //applyInitializers() 調(diào)用之前加載所有的ApplicationContextInitializer的initialize()方法

? ? ? ? ? ? //同時(shí)調(diào)用之前加載所有的SpringApplicationRunListener的contextPrepared()方法

? ? ? ? ? ? this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

? ? ? ? ? ? //prepareContext運(yùn)行完成時(shí) 再調(diào)用所有的SpringApplicationRunListeners的contextLoaded()方法


? ? ? ? ? ? //重構(gòu)ioc容器,就是ioc容器的初始化(如果是web應(yīng)用,還會(huì)創(chuàng)建嵌入式的tomcat)

? ? ? ? ? ? this.refreshContext(context);

? ? ? ? ? ? this.afterRefresh(context, applicationArguments);

? ? ? ? ? ? stopWatch.stop();

? ? ? ? ? ? if (this.logStartupInfo) {

? ? ? ? ? ? ? ? (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);

? ? ? ? ? ? }

? ? ? ? ? ? //回調(diào)所有的SpringApplicationRunListeners的start()方法

? ? ? ? ? ? listeners.started(context);

? ? ? ? ? ? //調(diào)用ApplicationRunner和CommandLineRunner的方法

? ? ? ? ? ? this.callRunners(context, applicationArguments);

? ? ? ? } catch (Throwable var10) {

? ? ? ? ? ? this.handleRunFailure(context, var10, exceptionReporters, listeners);

? ? ? ? ? ? throw new IllegalStateException(var10);

? ? ? ? }

? ? ? ? try {

? ? ? ? ? ? //調(diào)用所有的SpringApplicationRunListeners的running()方法

? ? ? ? ? ? listeners.running(context);

? ? ? ? ? ? //整個(gè)springboot應(yīng)用啟動(dòng)以后返回啟動(dòng)的ioc容器

? ? ? ? ? ? return context;

? ? ? ? } catch (Throwable var9) {

? ? ? ? ? ? this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);

? ? ? ? ? ? throw new IllegalStateException(var9);

? ? ? ? }

? ? }

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

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