一、SpringBoot启动的入口
1.当我们启动一个SpringBoot项目的时候,入口程序就是main方法,而在main方法中就执行了一个run方法。
@SpringBootApplication
public class StartApp {
public static void main(String[] args) {
// test
SpringApplication.run(StartApp.class);
}
}
2.SpringApplication.run方法
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
// 调用重载的run方法,将传递的Class对象封装为了一个数组
return run(new Class<?>[] {
primarySource }, args);
}
静态帮助器,可用于使用默认设置和用户提供的参数从指定的源运行{@link SpringApplication}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
// 创建了一个SpringApplication对象,并调用其run方法
// 1.先看下构造方法中的逻辑
// 2.然后再看run方法的逻辑
return new SpringApplication(primarySources).run(args);
}
3.SpringApplication构造器
创建一个新的{
@link SpringApplication}实例。应用程序上下文将从指定的主源加载bean(参见{
@link SpringApplication class-level}文档了解详细信息)。可以在调用之前自定义实例
public SpringApplication(Class<?>... primarySources) {
// 调用其他的构造方法
this(null, primarySources);
}
this(null, primarySources);方法进入:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 传递的resourceLoader为null
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 记录主方法的配置类名称
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 记录当前项目的类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 加载配置在spring.factories文件中的ApplicationContextInitializer对应的类型并实例化
// 并将加载的数据存储在了 initializers 成员变量中。
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 初始化监听器 并将加载的监听器实例对象存储在了listeners成员变量中
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 反推main方法所在的Class对象 并记录在了mainApplicationClass对象中
this.mainApplicationClass = deduceMainApplicationClass();
}
在本方法中完成了几个核心操作
- 推断当前项目的类型 this.webApplicationType是SERVLET;
- 加载配置在spring.factories文件中的ApplicationContextInitializer中的类型并实例化后存储在了initializers中。
ApplicationContextInitializer
getSpringFactoriesInstances(XXX.class)方法的作用是加载spring.factories文件中的kv对,后续获取XXX的对象从map中取不用在加载文件了。 - 和2的步骤差不多,完成监听器的初始化操作,并将实例化的监听器对象存储在了listeners成员变量中
- 通过StackTrace反推main方法所在的Class对象
4.SpringApplication的run方法:
public ConfigurableApplicationContext run(