启动项目
SpringBoot项目有一个主程序启动类,在主程序启动勒种有个启动项目main()方法,通过执行SpringApplication.run()启动整个SpringBoot程序
@SpringBootApplication
public class SpringbootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}
public static ConfigurableApplicationContext run(Class<?> primarySource,
String... args) {
return run(new Class[]{primarySource}, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
从源码中可以看出来,SpringApplication.run()方法内部执行了两个操作,分别是SpringApplication实例的初始化和调用run()启动项目
SpringApplication实例的初始化
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
//把项目启动类.class设置为属性存储起来
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//判断当前webApplicationType应用的类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//初始化器,最后会调用这些初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//设置监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//用于推断并设置项目main()方法启动主程序启动类
this.mainApplicationClass = deduceMainApplicationClass();
}
从上诉源码中可以看出来,SpringApplication的初始化过程包括4部分
- this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
用于判断webApplicationType应用的类型。deduceFromClasspath()方法用于插手Classpath类路径下是否存在某个特征类,从而判断当前webApplicationType类似是SERVLETyingy (Spring5之前的传统MVC应用)还是REACTIVE应用(Spring5开始出现的WebFlux交互式应用)
- setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
用于SpringApplication应用的初始化器设置。在初始化器设置的过程中,会使用Spring类加载器SpringFactoriesLoader从META-INF/spring.factories类路径下的ጱMETA-INF/spring.factores文件中获取所有可用的应用初始化器类ApplicationContextInitializer
- setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
用于SpringApplication应用的监听器设置。监听器设置的过程与上一步初始化器设置基本一样,也是使用SpringFactoriesLoader从META-INF/spring.factories类路径下的ጱMETA-INF/spring.factores文件中获取所有可用的应用初始化器类ApplicationListener。
- this.mainApplicationClass = deduceMainApplicationClass();
项目初始化
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//第一步 获取并启动监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//第二步 根据SpringApplicationRunListeners以及参数来准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
//第三步 创建Spring容器
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;
}