- Author: HuiFer
- 源码阅读仓库: SourceHot-spring-boot
看到调用堆栈
- 一步一步回上去看如何调用具体方法的
- 配置文件监听器
org.springframework.boot.context.config.ConfigFileApplicationListener#addPropertySources
protectedvoidaddPropertySources(ConfigurableEnvironmentenvironment, ResourceLoaderresourceLoader) {
RandomValuePropertySource.addToEnvironment(environment);
// 加载器加载信息newLoader(environment, resourceLoader).load();
}- 配置资源加载器
构造方法
Loader(ConfigurableEnvironmentenvironment, ResourceLoaderresourceLoader) {
// 环境配置this.environment = environment;
// 占位符处理器this.placeholdersResolver = newPropertySourcesPlaceholdersResolver(this.environment);
// 资源加载器this.resourceLoader = (resourceLoader != null) ? resourceLoader : newDefaultResourceLoader();
// 配置信息加载器初始化this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
getClass().getClassLoader());
}熟悉的老朋友
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader()), 看看**spring.factories**有什么
观察发现里面有一个YamlPropertySourceLoader和我们之前找 yml 字符串的时候找到的类是一样的。说明搜索方式没有什么问题。
初始化完成,后续进行解析了
voidload() {
FilteredPropertySource.apply(this.environment, DEFAULT_PROPERTIES, LOAD_FILTERED_PROPERTY,
(defaultProperties) -> {
this.profiles = newLinkedList<>();
this.processedProfiles = newLinkedList<>();
this.activatedProfiles = false;
this.loaded = newLinkedHashMap<>();
// 初始化配置文件initializeProfiles();
while (!this.profiles.isEmpty()) {
Profileprofile = 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));
addLoadedPropertySources();
applyActiveProfiles(defaultProperties);
});
}org.springframework.boot.context.config.ConfigFileApplicationListener.Loader#load(org.springframework.boot.context.config.ConfigFileApplicationListener.Profile, org.springframework.boot.context.config.ConfigFileApplicationListener.DocumentFilterFactory, org.springframework.boot.context.config.ConfigFileApplicationListener.DocumentConsumer)
privatevoidload(Profileprofile, DocumentFilterFactoryfilterFactory, DocumentConsumerconsumer) {
getSearchLocations().forEach(
// 本地路径
(location) -> {
// 是不是文件夹booleanisFolder = location.endsWith("/");
// 文件名,默认applicationSet<String> names = isFolder ? getSearchNames() : NO_SEARCH_NAMES;
// 循环加载names.forEach((name) -> {
load(location, name, profile, filterFactory, consumer);
});
});
}- 资源路径可能性
该方法采用循环每个路径下面都去尝试一遍
- 中间过程省略,我们直接看最后的加载行为
org.springframework.boot.context.config.ConfigFileApplicationListener.Loader#loadDocuments
privateList<Document> loadDocuments(PropertySourceLoaderloader, Stringname, Resourceresource)
throwsIOException {
// 文档的缓存keyDocumentsCacheKeycacheKey = newDocumentsCacheKey(loader, resource);
// 文档信息List<Document> documents = this.loadDocumentsCache.get(cacheKey);
if (documents == null) {
// 执行加载,将配置文件读取返回List<PropertySource<?>> loaded = loader.load(name, resource);
// 数据转换documents = asDocuments(loaded);
// 缓存设置this.loadDocumentsCache.put(cacheKey, documents);
}
returndocuments;
}此处的loader.load()调用具体的 loader 实现类进行执行方法
@OverridepublicList<PropertySource<?>> load(Stringname, Resourceresource) throwsIOException {
if (!ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
thrownewIllegalStateException(
"Attempted to load " + name + " but snakeyaml was not found on the classpath");
}
// 将资源转换成集合对象List<Map<String, Object>> loaded = newOriginTrackedYamlLoader(resource).load();
if (loaded.isEmpty()) {
returnCollections.emptyList();
}
List<PropertySource<?>> propertySources = newArrayList<>(loaded.size());
for (inti = 0; i < loaded.size(); i++) {
StringdocumentNumber = (loaded.size() != 1) ? " (document #" + i + ")" : "";
// 放入返回结果中propertySources.add(newOriginTrackedMapPropertySource(name + documentNumber,
Collections.unmodifiableMap(loaded.get(i)), true));
}
returnpropertySources;
}PropertiesPropertySourceLoader解析同理不在次展开描述了
/** * 将 {@link PropertySource} 转换成 {@link Document} * @param loaded * @return */privateList<Document> asDocuments(List<PropertySource<?>> loaded) {
if (loaded == null) {
returnCollections.emptyList();
}
returnloaded.stream().map(
// 循环创建新对象
(propertySource) -> {
// 对象创建Binderbinder = newBinder(ConfigurationPropertySources.from(propertySource),
this.placeholdersResolver);
/** * 通过 {@link Binder} 将数据进行绑定,创建 {@link Document}进行返回 */returnnewDocument(propertySource, binder.bind("spring.profiles", STRING_ARRAY).orElse(null),
getProfiles(binder, ACTIVE_PROFILES_PROPERTY),
getProfiles(binder, INCLUDE_PROFILES_PROPERTY));
}).collect(Collectors.toList());
}









