Springboot 加载配置文件源码分析
本文的分析是基于springboot 2.2.0.RELEASE。
本篇文章的相关源码位置:https://github.com/wbo112/blogdemo/tree/main/springbootdemo/springboot-profiles
springboot加载配置文件如application.yml是通过org.springframework.boot.context.config.ConfigFileApplicationListener这个类来完成的。这个类的加载也是通过spring.factories文件中来加载的。
ConfigFileApplicationListener这个类同时实现了EnvironmentPostProcessor、ApplicationListener这两个接口。
EnvironmentPostProcessor接口需要实现的postProcessEnvironment方法,这个方法主要就是用来对Environment来进行增强处理的。而Environment主要是用来表示当前应用程序运行环境的接口。在我们这里来说读取的配置文件最终也会放到这里面来。
简单的调用关系就是下面的图来,具体是怎么调到onApplicationEvent的,比较简单,就不和大家一起看了。直接看本次的重点吧。
下面的方法都是ConfigFileApplicationListener这个类中
在addPropertySources中首先会添加一个用来处理生成随机数的RandomValuePropertySource,然后就会通过内部类Loader来加载配置文件。所以我们本次的主要是看Loader类的load方法的执行流程
下面我们来具体看看load方法的执行流程
void load() {
//配置文件的加载就是通过这里来完成的。
//DEFAULT_PROPERTIES = "defaultProperties";
//LOAD_FILTERED_PROPERTY是一个set<String>,里面有两个元素{"spring.profiles.active","spring.profiles.include"}
FilteredPropertySource.apply(this.environment, DEFAULT_PROPERTIES, LOAD_FILTERED_PROPERTY,
//下面这里是一个lambda表达式,这里暂时省略,后面具体调用到这里我们再具体看。
(defaultProperties) -> {
......
});
}
上面的会调用到FilteredPropertySource的静态方法,这个也比较简单,就几行代码。最终又会调用到上面我们的省略的lambda表达式
static void apply(ConfigurableEnvironment environment, String propertySourceName, Set<String> filteredProperties,
Consumer<PropertySource<?>> operation) {
//这个是获取到当前程序的运行时环境。主要就是当前系统的环境变量、当前程序的环境变量等等,下面放个图一起看看
MutablePropertySources propertySources = environment.getPropertySources();
//这里是从运行时环境中查找key=defaultProperties的属性值,一般情况下,我们没有配置这个属性,获取到的original就是null,就会走到下面的if分支中,回到我们的lambda表达式中,我们就看这个分支吧
PropertySource<?> original = propertySources.get(propertySourceName);
if (original == null) {
operation.accept(null);
return;
}
propertySources.replace(propertySourceName, new FilteredPropertySource(original, filteredProperties));
try {
operation.accept(original);
}
finally {
propertySources.replace(propertySourceName, original);
}
}
我们看看上面的MutablePropertySources propertySources = environment.getPropertySources();里面的内容