使用debug模式去运行程序,阅读源码
初始化流程
spring 容器的初始化
创建了SpringApplication对象实例,实例中通过path去判段使用的web容器的类型,并且调用了对象实例的run方法
run方法中启动了计时器,创建并启动所有监听器,初始化运行环境(加载配置),
判断应该创建哪一种ApplicationContext,创建后和环境绑定
通过SpringFactoris-Loader加载classpath中的所有spring-Initializer,对context在refresh做处理,通知监听器Context准备好了
将@EnableAutoConfiguration获取的所有配置一起其他IOC容器配置加载到ApplicationContext
Spring boot程序入口,最后调用了run方法
@SpringBootApplication
public class LearnApplication {
public static void main(String[] args) {
SpringApplication.run(LearnApplication.class, args);
}
}
调用静态的run方法之后,去新建一个SpringApplication对象
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
SpringApplication的构造方法
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));
this.webApplicationType = WebApplicationType.deduceFromClasspath();//判断web应用的类型
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
webApplication的判断逻辑
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
return REACTIVE;
} else {
String[] var0 = SERVLET_INDICATOR_CLASSES;
int var1 = var0.length;
for(int var2 = 0; var2 < var1; ++var2) {
String className = var0[var2];
if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
return NONE;
}
}
return SERVLET;
}
}
回到具体调用的run方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();//启动计时器
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();//设置headless模式,该模式一般用于服务端没有显示器、键盘、鼠标等设备的情况
SpringApplicationRunListeners listeners = this.getRunListeners(args);//创建listeners
listeners.starting();//启动所有的监听器
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);//初始化环境,包括加载配置文件、profiles
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);//Banner可以定义springboot启动输出的图形
context = this.createApplicationContext();//根据new SpringBootApplication构造函数中web容器类型去初始化容器
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);//过SpringFactoris-Loader加载classpath中的所有spring-Initializer
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);//配置springboot将要使用的环境,在容器初始化之前调用initializer
this.refreshContext(context);//判断是否注册ShutdownHoo,该方法后IOC容器可用
this.afterRefresh(context, applicationArguments);//通过SpringFactoris-Loader加载classpath中的所有spring-Initializer,对context做处理
stopWatch.stop();//Application创建好计时器结束
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}