共计 3538 个字符,预计需要花费 9 分钟才能阅读完成。
接着上文,咱们进入 spring 的环境筹备办法中:
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, | |
ApplicationArguments applicationArguments) { | |
// Create and configure the environment | |
ConfigurableEnvironment environment = getOrCreateEnvironment(); | |
configureEnvironment(environment, applicationArguments.getSourceArgs()); | |
ConfigurationPropertySources.attach(environment); | |
listeners.environmentPrepared(environment); | |
bindToSpringApplication(environment) | |
if (!this.isCustomEnvironment) {environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, | |
deduceEnvironmentClass()); | |
} | |
ConfigurationPropertySources.attach(environment); | |
return environment; | |
} |
其中 getOrCreateEnvironment 会依据以后的 webApplicationType 的类型来创立环境的类型,如果是 SERVLET 类型的话,会创立一个 StandardServletEnvironment 对象。这里的 environmentPrepared 办法 ApplicationEnvironmentPreparedEvent 类型的事件。依据事件类型获取监听器,咱们来察看比拟重要的监听器:ConfigFileApplicationListener,在这个类型实现了咱们配置文件的解析。进入到其 onApplicationEvent 办法可知:次要是获取到环境筹备的后置处理器(EnvironmentPostProcessor),并调用它们的 postProcessEnvironment 办法。值得注意的是 ConfigFileApplicationListener 本身也实现了 EnvironmentPostProcessor 接口,也是 ConfigFileApplicationListener 实现了对配置文件的解析。
public void onApplicationEvent(ApplicationEvent event) {if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event); | |
} | |
if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent(event); | |
} | |
} | |
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {List<EnvironmentPostProcessor> postProcessors = loadPostProcessors(); | |
postProcessors.add(this); | |
AnnotationAwareOrderComparator.sort(postProcessors); | |
for (EnvironmentPostProcessor postProcessor : postProcessors) {postProcessor.postProcessEnvironment(event.getEnvironment(), event.getSpringApplication()); | |
} | |
} |
跟进 ConfigFileApplicationListener 进入 load 办法:
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)); | |
addLoadedPropertySources(); | |
applyActiveProfiles(defaultProperties); | |
}); | |
} |
持续进入这里的 load 办法
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)); | |
}); | |
} |
这俩的 getSearchLocations 办法是获取搜寻的门路,springboot 默认的门路为:DEFAULT_SEARCH_LOCATIONS = “classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/”; 获取多个搜寻门路之后,别离调用 load 办法。
private Set<String> getSearchLocations() {Set<String> locations = getSearchLocations(CONFIG_ADDITIONAL_LOCATION_PROPERTY); | |
if (this.environment.containsProperty(CONFIG_LOCATION_PROPERTY)) {locations.addAll(getSearchLocations(CONFIG_LOCATION_PROPERTY)); | |
} | |
else { | |
locations.addAll(asResolvedSet(ConfigFileApplicationListener.this.searchLocations, DEFAULT_SEARCH_LOCATIONS)); | |
} | |
return locations; | |
} |
在这里的 load 办法里,有对应的 PropertiesPropertyResourceLoader 和 YamlPropertyResourceLoader 别离用于解析 (propertes、xml) 文件和 (yml、yaml) 文件。
到这里配置文件的解析曾经实现。