啟動(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,然后保存起來
? ? ? ? this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
? ? ? ? //從類路徑下的META-INF下的spring.factories下找到所有的ApplicationListener類,保存起來
? ? ? ? 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);
? ? ? ? }
? ? }