spring_boot查找配置文件源码分析

源码分析

1.找到配置文件

2.根据profile加载对应的文件或属性

3.把加载后的属性放到spring 容器中

spring boot项目的入口为main方法

加载配置的入口是有设计的。是观察者设计模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SpringApplication.run(SpringLogbackApplication.class, args);
new SpringApplication(primarySources)
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
spring.factories
ConfigFileApplicationListener


public ConfigurableApplicationContext run(String... args)
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
listeners.environmentPrepared(environment);
ConfigFileApplicationListener.onApplicationEvent(ApplicationEvent event)
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event)
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application)
protected void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader)
new Loader(environment, resourceLoader).load();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void load() {
FilteredPropertySource.apply(this.environment, DEFAULT_PROPERTIES, LOAD_FILTERED_PROPERTY,
(defaultProperties) -> {
this.profiles = new LinkedList<>();
this.processedProfiles = new LinkedList<>();
this.activatedProfiles = false;
this.loaded = new LinkedHashMap<>();
initializeProfiles();
while (!this.profiles.isEmpty()) {
Profile profile = this.profiles.poll();
if (isDefaultProfile(profile)) {
addProfileToEnvironment(profile.getName());
}
// 加载配置文件
load(profile, this::getPositiveProfileFilter,
addToLoaded(MutablePropertySources::addLast, false));
this.processedProfiles.add(profile);
}
load(null, this::getNegativeProfileFilter, addToLoaded(MutablePropertySources::addFirst, true));
// 添加到spring 环境
addLoadedPropertySources();
// 设置启用的profile
applyActiveProfiles(defaultProperties);
});
}
1
2
3
4
5
6
7
private void load(Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
getSearchLocations().forEach((location) -> {
boolean isDirectory = location.endsWith("/");
Set<String> names = isDirectory ? getSearchNames() : NO_SEARCH_NAMES;
names.forEach((name) -> load(location, name, profile, filterFactory, consumer));
});
}

这里涉及到3个值:去哪里找配置文件(location)、配置文件的名称是什么(getSearchNames)、不同环境(profile)

location位置: classpath:/, classpath:/config/, file:./, file:./config/ 优先级从低到高,最先加载file:./config/ 位置的配置文件;如果配置了spring.config.location属性则取这个属性的值。

配置文件的名字:默认值为:application;如果配置了spring.config.name属性则取改属性值。

环境为上面传进来的:自定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void load(String location, String name, Profile profile, DocumentFilterFactory filterFactory,
DocumentConsumer consumer) {
if (!StringUtils.hasText(name)) {
for (PropertySourceLoader loader : this.propertySourceLoaders) {
if (canLoadFileExtension(loader, location)) {
load(loader, location, profile, filterFactory.getDocumentFilter(profile), consumer);
return;
}
}
throw new IllegalStateException("File extension of config file location '" + location
+ "' is not known to any PropertySourceLoader. If the location is meant to reference "
+ "a directory, it must end in '/'");
}
Set<String> processed = new HashSet<>();
for (PropertySourceLoader loader : this.propertySourceLoaders) {
for (String fileExtension : loader.getFileExtensions()) {
if (processed.add(fileExtension)) {
loadForFileExtension(loader, location + name, "." + fileExtension, profile, filterFactory,
consumer);
}
}
}
}

到这里就根据不同的文件名后缀来获取了。

所有的扩展名: properties xml yml yaml

参考

Application ConfigFileApplicationListener

https://blog.csdn.net/weixin_43732955/article/details/106600869

bootstrap BootstrapApplicationListener

https://baijiahao.baidu.com/s?id=1720638939882107917&wfr=spider&for=pc


spring_boot查找配置文件源码分析
http://hanqichuan.com/2022/06/22/spring/spring_boot查找配置文件源码分析/
作者
韩启川
发布于
2022年6月22日
许可协议