文章仅从源码的角度探讨springboot2.x的原理,不探讨使用。
我们知道Springboot是靠着这段代码进行启动的。
public static void main(String[] args) {
SpringApplication.run(XxxApplication.class, args);
}
分析源码的话,理所当然从这里下手。
通过定位到源码,我们发现这里有两步。一步是初始化SpringApplication对象,一步是调用run方法进行来完成启动。
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
对于SpringApplication初始化的源码,主要就是对相关的属性进行赋值。(this.xxx = xxx)
下面看一下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);
}
}
表面上看只有三十多行代码,其实背后的代码量是非常高的。
上面我们大致清楚了springboot的启动,本质就是初始化SpringApplication对象后,调用run方法。在扣细节之前,有必要整体认识一下springboot启动做了哪些事情:
框架初始化分为:
- 配置资源加载器
- 配置primarySources(一般是我们的启动类)
- 应用环境的检测(springboot1.x版本有两种环境,标准环境和web环境,spingboot2.x添加了一种Reactive环境)
- 配置系统初始化器
- 配置应用监听器
- 配置main方法所在类
接着就是框架的基本启动
- 计时器开始计时
- Headless模式赋值
- 发送ApplicationStartingEvent
- 配置环境模块
- 发送ApplicationEnvironmentPreparedEvent
- 打印banner
- 创建应用上下文对象
- 初始化失败分析器
- 关联springboot组件与应用上下文对象
- 发送ApplicationContextInitalizedEvent
- 加载sources到context
- 发送ApplicationPreparedEvent
- 刷新上下文(完成bean的加载)
- 计时器停止计时
- 发送ApplicationStartedEvent事件
- 调用框架启动扩展类
- 发送ApplicationReadyEvent
通过以上步骤完成基本的启动,后面还有框架的自动化装配的内容:
- 收集配置文件中的配置工厂类
- 加载组件工厂
- 注册组件内定义 bean
文字描述,可能不太直观,这里用图示整体梳理一下:
下面一起扣细节吧。
转载:https://blog.csdn.net/qq_42322103/article/details/105146224
查看评论