首先说明的是ConfigFileApplicationListener.java是加载解析处理application的地方.上面的图是非常省略的图,只画了个大概的流程.下面来仔细的说明说下
1.最开始的起来在SpringApplication里面这里是从spring.factories里面读取配置,而我们所需要的类ConfigFileApplicationListeneryi就是从这里读出来的,也就是起始地方.看下具体数据
这个类被读取出来后,在适当的地方会被加载到beanfactory的Listener里面,具体的地方看下面.这里调用addApplicationListener注册到工厂里面,也就是AbstractApplicationContext的addApplicationListener接口.代码自行去看.
2在refresh()初始始容器的时候有这么个函数调用.这里就是将我们先前注册的对象,取出来...下面细节不说了,直接到具体的处理函数里面吧
postProcessEnvironment->addPropertySources-.>Loader->load
1.经过一些操作之后,最终会触发ConfigFileApplicationListener的函数postProcessEnvironment的调用,最后走到最后实现的地方load操作.这里对这个函数进行深入分析.
private Set<String> getSearchLocations() {
if (this.environment.containsProperty(CONFIG_LOCATION_PROPERTY)) {
return getSearchLocations(CONFIG_LOCATION_PROPERTY);
}
Set<String> locations = getSearchLocations(CONFIG_ADDITIONAL_LOCATION_PROPERTY);
locations.addAll(
asResolvedSet(ConfigFileApplicationListener.this.searchLocations, DEFAULT_SEARCH_LOCATIONS));
return locations;
}
//上面的这段函数,主要是给出搜索路径,路径如下
public static final String CONFIG_ADDITIONAL_LOCATION_PROPERTY = **"spring.config.additional-location";**
private static final String DEFAULT_SEARCH_LOCATIONS = **"classpath:/,classpath:/config/,file:./,file:./config/";** 这里面以,号进行切割
private void load(Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
getSearchLocations().forEach((location) -> {
boolean isFolder = location.endsWith("/");
Set<String> names = isFolder ? getSearchNames() : NO_SEARCH_NAMES;
//这里对所有的搜索路径进行搜索.getSearchNames返回是的application这个值
names.forEach((name) -> load(location, name, profile, filterFactory, consumer));
});
}
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;
}
}
}
//下面这段是重点,看图好说点.
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);
}
}
}
}
1.我们知道要找以application开头的配置文件,但后缀名没给出来,所以下面就是要得到后缀名了
2看propertySourceLoaders这个初始化,以及getFileExtensions函数调用.首先来看init好了,这里也是读取配置文件.看里面给出的是什么类
这里面给了两个类,分别看下这两个类的getFileExtensions实现.
第一个类
第二个类可以看出后缀分别是properties", “xml”,“yml”,“yaml”
前缀有了,后缀有了就可以开始读取数据了.如下
loadForFileExtension(loader, location + name, “.” + fileExtension, profile, filterFactory…
location + name, “.” + fileExtension这里进行字符串拼接啦.难道直接搜怎么都搜不到
好了,就到这里了.后面就是各自调用自己的load函数来加载解析数据了.具体的细节自己看啦