SpringBoot 2.4.3
SpringBoot 启动源码分析
启动类run()方法跟进去有两步,一是初始化,二是SpringApplication.run()方法的执行
初始化
1.配置resourceLoader
2.判断当前应用程序的类型
3.获取初始化容器实例对象
4.找到当前应用程序的主类,开始执行
.
运行
1.获取并启动监听器
2.构造容器环境,初始化默认应用参数类。根据运行监听器和应用参数来准备Spring环境
3.第三步:创建容器(应用上下文)
4.
5.准备容器
6.刷新容器
main
@SpringBootApplication
public class TestApplication {
public static void main(String[] args){SpringApplication.run(TestApplication.class, args);}
}
一 初始化
1.配置resourceLoader
2.判断当前应用程序的类型
3.获取初始化容器实例对象
4.找到当前应用程序的主类,开始执行
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));
//获取ApplicationContextInitializer,也是在这里开始首次加载spring.factories文件
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//获取监听器,这里是第二次加载spring.factories文件
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
1 配置resourceLoader
2 判断当前应用程序的类型
webApplicationType = Servlet
3 获取初始化容器实例对象
getSpringFactoriesInstances – loadFactoryNames 获取工厂实例
loadFactoryNames
loadSpringFactories
读取 key value 通过反射进行实例化
加载配置文件 spring.factories
其中 Application Listeners 监听器为9个。
还有1个是:org.springframework.boot.autoconfigure.BackgroundPreinitializer
这10个监听器会贯穿springBoot整个生命周期。
createSpringFactoriesInstances
创建对象实例 实例化7个对象
4 找到当前应用程序的主类,开始执行
deduceMainApplicationClass
继续后面的流程。进入run方法
二 Run
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();//时间监控
stopWatch.start();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
//java.awt.headless是J2SE的一种模式用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true,系统变量默认为true
configureHeadlessProperty();
//获取spring.factories中的监听器变量,args为指定的参数数组,默认为当前类SpringApplication
//第一步:获取并启动监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//第二步:构造容器环境,初始化默认应用参数类,设置命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//根据运行监听器和应用参数来准备Spring环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
//设置需要忽略的bean
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);//打印banner
//第三步:创建容器(应用上下文)
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
//第四步:实例化SpringBootExceptionReporter.class,用来支持报告关于启动的错误
//第五步:准备容器
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//第六步:刷新容器
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, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
1 加载并启动监听器
获取11个监听器,加载到缓存,根据事件进行匹配
starting()
1.1 创建监听器对象
创建监听器对象SpringApplicationRunListener 从配置文件中读取到EventPublishingRunListener
Spring事件发布(监听)机制,回调机制,观察者模式
multicastEvent
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
11+1 EventPublishingRunListener、ApplicationStartingEvent
从配置文件中读取 EventPublishingRunListener
创建EventPublishingRunListener对象,并且创建出SimpleApplicationEventMultiCaster,将application的11个监听器给到当前对象,此时才能方面我们从中获取出符合监听事件的几个监听器。
将11个对象放到当前listeners中,向下开始
for循环
1.3 获取监听器的实例对象
EventPublishingRunListener
构造方法
addApplicationListener
这是一个内部类,用来保存所有的监听器。也就是在这一步,将spring.factories中的监听器传递到SimpleApplicationEventMulticaster中
supportEvent
遍历11个监听器,从过滤器中匹配出当前事件,把可以监听ApplicationStartingEvent 事件拿出来,并启动。
4 ConfigurationApplicationContext 未实现
未实现
2 解析参数值,构造容器环境,初始化默认应用参数类
从命令行中解析参数值,设置命令行参数 --key=value 如 javar -D --server.port=8085 Test.jar,并进行匹配
//第二步:构造容器环境,初始化默认应用参数类
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//根据运行监听器和应用参数来准备Spring环境 创建和配置环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
DefaultApplicationArguments
Source
SimpleCommandLinePropertySource.java
SimpleCommandLineArgsParser
创建Servlet环境
prepareEnvironment()
getOrCreateEnvironment() = this.webApplicationType //创建Servlet 环境对象
attach()//加载一些环境属性值
4
5将
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// 1 构建一个标准的Servlet环境
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
//3 附加一些环境属性值
ConfigurationPropertySources.attach(environment);
//4 监听器启动时的环境准备工作
listeners.environmentPrepared(bootstrapContext, environment);
DefaultPropertiesPropertySource.moveToEnd(environment);
configureAdditionalProfiles(environment);
//5 将当前的环境绑定到Application中
bindToSpringApplication(environment);
//6 判断环境对象是否符合当前类型,不符合再进行转换
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
//7 增加其他属性
ConfigurationPropertySources.attach(environment);
return environment;
}
getOrCreateEnvironment
1
查看类图
StandarServletEnvironment.java(spring-web包)
引入 servlet中两个最基础的配置:servletContextInitParams、servletConfigInitParams
将服务设置到当前环境中去,同时也包含系统参数 systemEnvironment
添加参数转化器服务 ConversionService
添加参数转化器服务 ConversionService
设置环境变量
设置命令行参数,默认为null
getSharedInstance();//返回一个共享的Application的实例
configureProfiles(environment, args)
getActiveProfiles()
根据属性值spring.profiles.active 判断当前开发环境 dev环境、production环境
注:此时未加载application.yml文件
根据属性值spring.profiles.active,判断环境配置参数
从11个监听器中找出7个集合
配置文件
loadPostProcessors
EnvironmentPostProcessor.class
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor,\
org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor
最后通过for循环加入EnvironmentPostProcessor
addToEnvironment
RandomValuePropertySource 是配置文件中使用了${random}函数
RandomValuePropertySource.addToEnvironment()
postProcessEvnironment
SystemEnvironmentPropertySourceEnvironmentPostProcessor.postProcessEvnironment()
加载 ProperttySource Loaders
new Loader(environment, resourceLoader).load();
yml
YamlPropertySourceLoader.class