​ Springboot的启动过程总结 ​


1、总体步骤分两个

  • 创建Spring 应用(创建SpringApplication)



  • 运行Spring 应用(运行SpringApplication)

2、创建Spring 应用(创建SpringApplication)

就是new 一个对象,构造器里面做一些初始化的动作



public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//判断应用的类型deduce v. 推论; 推断; 演绎;的意思
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//设置初始化器,保存起来 从spring.factories 找
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//设置监听器、保存起来从spring.factories 找
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//主应用类是那个
this.mainApplicationClass = deduceMainApplicationClass();
}


3、运行Spring 应用(运行SpringApplication)



public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//获取所有的运行监听器:就一个EventPublishingRunListener从spring.factories 中找的
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境,如果有的话就不创建了,没有就创建一个
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}

try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}


3.1 prepareEnvironment 方法说明

/**
*
*  获取或者创建一个Environment对象,如果我们自己在main 方法里面创建了一个Environment,并放到
*        SpringApplication 中了就不创建了,
*        SpringApplication application = new SpringApplication(ProfileDemoApplication.class);
*        ConfigurableEnvironment environment = new StandardEnvironment();
*        environment.setActiveProfiles("dev");
*        application.setEnvironment(environment);
*  否则就创建
*
*
*/
注意:以下的说明
// 添加初始的properties(注意:当前并未加载如application.properties/yml的properties)
// 添加初始的profile(注意:当前并未加载如application.properties/yml配置profile)



private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
//创建或者获取一个Environment 对象
ConfigurableEnvironment environment = getOrCreateEnvironment();
//配置environment
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
// 触发监听器(主要是触发ConfigFileApplicationListener,这个监听器将会加载如application.properties/yml这样的配置文件)
//通知所有的监听器 环境准备好了
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}