springboot启动:在Application中通过SpringApplication.run()方法,并向其中传入主类以及args来完成启动
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
那么springboot是怎么通过run这行代码来启动springboot呢?
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
通过源码可以看到,它一共分为两步,首先实例化一个SpringApplication对象,其次调用它的run方法。
1.框架初始化(new SpringApplication(primarySources))
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
this.webApplicationType = this.deduceWebApplicationType();
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
- 配置资源加载器
- 配置primarySources
- 应用环境检测
- 配置系统初始化器
- 配置应用监听器
- 配置main方法所在类
2.框架启动(调用run方法)
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
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);
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);
}
}
- 计时器开始计时
- Headless模式赋值
- 获取监听器
- 发送ApplicationStartingEvent
- 构造容器环境
- 发送ApplicationEnvironmentPreparedEvent
- 设置需要忽略的Bean
- 打印banner
- 创建上下文对象
- 实例化SpringBootExceptionReporter.class(失败分析器),用来支持报告关于启动的错误
- 关联springboot组件与应用上下文对象
- 发送ApplicationContextInitializedEvent
- 加载source到context
- 发送ApplicationPreparedEvent
- 刷新上下文
- 计时器停止计时
- 发送ApplicationStartedEvent
- 调用框架启动扩展类
- 发送ApplicationReadyEvent
3.框架自动化装备(属于框架启动部分)
- 收集配置文件中的配置工厂类
- 加载组件工厂
- 注册组件内定义的bean
由此可见虽然我们启动springboot只用了一行代码,但其背后的原理和步骤还是比较多的