springboot源码(三)
springboot启动入口run方法源码分析(一)
public class UserApplication { public static void main(String[] args) { SpringApplication.run(UserApplication.class,args); } }
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { return run(new Class[]{primarySource}, args); }
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
//两部分:1、SpringApplication构造方法;
2、run方法; return (new SpringApplication(primarySources)).run(args); }
1、先来看SpringApplication构造方法public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
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();
//将spring.factories中key为ApplicationContextInitializer对应的类型实例化后放到成员变量initializers里
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
将spring.factories中key为ApplicationListener的对应类型实例化后放到成员变量listeners里
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
//反推main方法所在的类对象,并记录在mainApplicationClass中
this.mainApplicationClass = this.deduceMainApplicationClass();
}
2、再来看run方法
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); this.configureHeadlessProperty();
//加载SpringApplicationRunListener得到事件发布器EventPublishingRunListener,会把SpingringApplication中的成员变量listener放到listeners中 SpringApplicationRunListeners listeners = this.getRunListeners(args);
//触发启动事件 listeners.starting(); Collection exceptionReporters; try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//创建并配置环境 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
//配置需要忽略的beanInfo信息 this.configureIgnoreBeanInfo(environment);
//打印Banner信息 Banner printedBanner = this.printBanner(environment);
//创建应用上下文对象 context = this.createApplicationContext();
//加载启动的异常信息 exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
//刷新前操作 this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//刷新应用上下文,完成spring容器初始化--》进到spring源码 this.refreshContext(context);
//刷新后操作 this.afterRefresh(context, applicationArguments); stopWatch.stop(); 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); }
return context; }
总结:
springApplication的构造方法中主要做了这么几件事:
- 记录当前的应用类型;
- 加载ApplicationContextInitializer并且放到SpringApplication的成员变量initializers中;
- 加载ApplicationListener并且放到SpringApplication的成员变量listeners中;
- 记录main方法所在的class对象,并且放到mainApplicationClass中;
run方法中主要做了这么几件事:
- 声明ConfigurableApplicationContext对象;
- 加载SpringApplicationRunListener得到事件发布器EventPublishingRunListener;
- 触发启动事件;
- 配置环境信息
- 过滤beaninfo信息;
- 生成banner信息;
- 创建应用上下文;
- 加载配置的启动异常的回调异常处理器;
- 刷新应用上下文,本质就是完成Spring容器的初始化操做;
- 完成对应的事件广播;
- 返回上下文对象;
主要步骤的具体讲解,留在下一篇。