this.mainApplicationClass = deduceMainApplicationClass();
}
在本方法中完成了几个核心操作
-
推断当前项目的类型
-
加载配置在spring.factories文件中的ApplicationContextInitializer中的类型并实例化后存储在了initializers中。
-
和2的步骤差不多,完成监听器的初始化操作,并将实例化的监听器对象存储在了listeners成员变量中
-
通过StackTrace反推main方法所在的Class对象
上面的核心操作具体的实现细节我们在后面的详细文章会给大家剖析
接下来我们在回到SpringApplication.run()方法中。
public ConfigurableApplicationContext run(String… args) {
// 创建一个任务执行观察器
StopWatch stopWatch = new StopWatch();
// 开始执行记录执行时间
stopWatch.start();
// 声明 ConfigurableApplicationContext 对象
ConfigurableApplicationContext context = null;
// 声明集合容器用来存储 SpringBootExceptionReporter 启动错误的回调接口
Collection exceptionReporters = new ArrayList<>();
// 设置了一个名为java.awt.headless的系统属性
// 其实是想设置该应用程序,即使没有检测到显示器,也允许其启动.
//对于服务器来说,是不需要显示器的,所以要这样设置.
configureHeadlessProperty();
// 获取 SpringApplicationRunListener 加载的是 EventPublishingRunListener
// 获取启动时到监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 触发启动事件
listeners.starting();
try {
// 构造一个应用程序的参数持有类
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 创建并配置环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 配置需要忽略的BeanInfo信息
configureIgnoreBeanInfo(environment);
// 输出的Banner信息
Banner printedBanner = printBanner(environment);
// 创建应用上下文对象
context = createApplicationContext();
// 加载配置的启动异常处理器
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 刷新前操作
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新应用上下文 完成Spring容器的初始化
refreshContext(context);
// 刷新后操作
afterRefresh(context, applicationArguments);
// 结束记录启动时间
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 事件广播 启动完成了
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
// 事件广播启动出错了
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 监听器运行中
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
// 返回上下文对象–> Spring容器对象
return context;
}
在这个方法中完成了SpringBoot项目启动的很多核心的操作,我们来总结下上面的步骤
-
创建了一个任务执行的观察器,统计启动的时间
-
声明ConfigurableApplicationContext对象
-
声明集合容器来存储SpringBootExceptionReporter即启动错误的回调接口
-
设置java.awt.headless的系统属性
-
获取我们之间初始化的监听器(EventPublishingRunListener),并触发starting事件
-
创建ApplicationArguments这是一个应用程序的参数持有类
-
创建ConfigurableEnvironment这时一个配置环境的对象
-
配置需要忽略的BeanInfo信息
-
配置Banner信息对象
-
创建对象的上下文对象
-
加载配置的启动异常的回调异常处理器
-
刷新应用上下文,本质就是完成Spring容器的初始化操作
-
启动结束记录启动耗时
-
完成对应的事件广播
-
返回应用上下文对象。
到此SpringBoot项目的启动初始化的代码的主要流程就介绍完成了。细节部分后面详细讲解。
写在最后
学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!
最后再分享的一些BATJ等大厂20、21年的面试题,把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。
Mybatis面试专题
MySQL面试专题
并发编程面试专题
实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。
[外链图片转存中…(img-TMvJdTd6-1714465015695)]
Mybatis面试专题
[外链图片转存中…(img-BHD8nhsY-1714465015696)]
MySQL面试专题
[外链图片转存中…(img-nIHyB70E-1714465015696)]
并发编程面试专题