springcloudconfig配置读取优先级过程详解
情景描述
最近在修复Eureka的静态页⾯加载不出的缺陷时,最终发现是远程GIT仓库将静态资源访问⽅式配置给禁⽤了
(sources.add-mappings=false)。虽然最后直接修改远程GIT仓库的此配置项给解决了(sources.add-mappings=true),但是从中牵涉出的配置读取优先级我们必须好好的再回顾下
springcloud config读取仓库配置
通过config client模块来读取远程的仓库配置,只需要在boostrap.properties⽂件中配置如下属性即可
spring.application.name=eureka
fig.uri=localhost:8888
fig.name=dev
fig.username=dev
fig.password=dev
外部源读取优先级
我们都知道spring的配置属性管理均是存放在Enviroment对象中,就以普通项⽬StandardEnvironment为例,其配置的存放顺序可罗列如下
顺位key来源说明
1commandLineArgs传⼊main函数的参数列表Program arguments
Properties()JDK属性列表、操作系统属性、-D开头的VM属性等
Env()环境属性,例如JAVA_HOME/M2_HOME
4${file_name}配置⽂件例如l
5defaultProperties SpringApplicationBuilder#properties()
那么远程读取的配置的存放应该放在上述的哪个位置呢?
我们都知道boostrap上下⽂通过暴露org.springframework.fig.PropertySourceLocator接⼝来⽅便集成第三⽅的外部源配置读取,⽐如本⽂提及的config client模块中的
org.fig.client.ConfigServicePropertySourceLocator实现类。
但最终将外部源配置读取以及插⼊⾄Environment对象中则是通过
org.springframework.fig.PropertySourceBootstrapConfiguration类来完成的。PropertySourceBootstrapConfiguration
此类也是ApplicationContextInitializer接⼝的实现类,阅读过cloud源码的都知道,此类被调⽤是在⼦类上下⽂初始化的时候,我们主要看下其复写的initialize()⽅法
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
CompositePropertySource composite = new CompositePropertySource(
BOOTSTRAP_PROPERTY_SOURCE_NAME);
// 对在boostrap上下⽂类型为PropertySourceLocator的bean集合进⾏排序
AnnotationAwareOrderComparator.sort(this.propertySourceLocators);
boolean empty = true;
ConfigurableEnvironment environment = Environment();
for (PropertySourceLocator locator : this.propertySourceLocators) {
PropertySource<?> source = null;
// 读取外部配置源
source = locator.locate(environment);
if (source == null) {
continue;
}
logger.info("Located property source: " + source);
composite.addPropertySource(source);
empty = false;
}
if (!empty) {
MutablePropertySources propertySources = PropertySources();
String logConfig = solvePlaceholders("${fig:}");
LogFile logFile = (environment);
if (ains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
}
/
/ 插⼊⾄Environment环境对象中
insertPropertySources(propertySources, composite);
reinitializeLoggingSystem(environment, logConfig, logFile);
setLogLevels(applicationContext, environment);
handleIncludedProfiles(environment);
}
}
直接观察对应的insertPropertySources()⽅法
private void insertPropertySources(MutablePropertySources propertySources,
CompositePropertySource composite) {
// 外部源配置集合
MutablePropertySources incoming = new MutablePropertySources();
incoming.addFirst(composite);
PropertySourceBootstrapProperties remoteProperties = new PropertySourceBootstrapProperties();
// 从外部源配置源集合中读取PropertySourceBootstrapProperties的相关属性
// 例如fig.overrideSystemProperties等属性
<(environment(incoming)).bind("fig",
Bindable.ofInstance(remoteProperties));
// fig.allow-override=false或者fig.override-none=false且fig.override-system-properties=true
if (!remoteProperties.isAllowOverride() || (!remoteProperties.isOverrideNone()
&& remoteProperties.isOverrideSystemProperties())) {
propertySources.addFirst(composite);
return;
}
// fig.override-none=true则处于最低读取位
if (remoteProperties.isOverrideNone()) {
propertySources.addLast(composite);
return;
}
// 根据fig.override-system-properties属性判断是放在systemProperties前还是后
if (propertySources
.contains(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME)) {
if (!remoteProperties.isOverrideSystemProperties()) {
propertySources.addAfter(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
composite);
}
else {
propertySources.addBefore(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
composite);
}
}
else {
propertySources.addLast(composite);
}
}
对上述的代码描述作下总结
1.上述的配置属性均会映射到PropertySourceBootstrapProperties实体类中,且其中的默认值罗列如下
属性默认值说明
fig.allow-override true外部源配置是否可被覆盖
fig.override-none false外部源配置是否不覆盖任何源
fig.override-system-properties true外部源配置是否可覆盖本地属性
2.针对相应的属性的值对应的外部源在Environment对象中的读取优先级,罗列如下
属性读取优先级fig.allow-override=false最⾼
fig.override-none=false&&fig.override-system-properties=true最⾼(默认)
fig.override-none=true最低
spring上下⽂⽆systemEnvironment属性最低
spring上下⽂有systemEnvironment属性 && fig.override-system-properties=false在systemEnvironment之后spring上下⽂有systemEnvironment属性 && fig.override-system-properties=false在systemEnvironment之前
即默认情况下,外部源的配置属性的读取优先级是最⾼的。
且除了fig.override-none=true的情况下,其他情况下外部源的读取优先级均⽐本地配置⽂件⾼。
Note:值得注意的是,如果⽤户想复写上述的属性,则放在l配置⽂件中是⽆效的,根据源码分析只能是⾃定义⼀个PropertySourceLocator接⼝实现类并放置在相应的spring.factories⽂件中⽅可⽣效。
⾃定义PropertySourceLocator接⼝
针对上⽂描述,假设有这么⼀个场景,远程仓库的配置都是公有的,我们也不能修改它,我们只在项⽬中去复写相应的配置以达到兼容的⽬的。那么⽤户就需要⾃定义去编写接⼝了
spring启动流程面试回答1.编写PropertySourceLocator接⼝实现类
figdemo.propertysource;
import org.springframework.fig.PropertySourceLocator;
import Ordered;
import annotation.Order;
import nv.Environment;
import nv.MapPropertySource;
import nv.PropertySource;
import java.util.HashMap;
import java.util.Map;
/**
* @author nanco
* @create 19/9/22
* @description ⾃定义的PropertySourceLocator的顺序应该要⽐远程仓库读取⽅式要优先
* @see org.fig.client.ConfigServicePropertySourceLocator
*/
@Order(value = Ordered.HIGHEST_PRECEDENCE + 1)
public class CustomPropertySourceLocator implements PropertySourceLocator {
private static final String OVERRIDE_ADD_MAPPING = "sources.add-mappings";
@Override
public PropertySource<?> locate(Environment environment) {
Map<String, Object> customMap = new HashMap<>(2);
// 远程仓库此配置为false,本地进⾏复写
customMap.put(OVERRIDE_ADD_MAPPING, "true");
return new MapPropertySource("custom", customMap);
}
}
2.编写BootstrapConfiguration
figdemo.propertysource;
import t.annotation.Bean;
import t.annotation.Configuration;
/**
* @author nanco
* @create 19/9/22
*/
@Configuration
public class CustomBootstrapConfiguration {
@Bean("customPropertySourceLocator")
public CustomPropertySourceLocator propertySourceLocator() {
return new CustomPropertySourceLocator();
}
}
3.在src\main\resources⽬录下创建META-INF\spring.factories⽂件
# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
4.运⾏main函数即可
⼩结
默认情况下,外部源配置拥有最⾼的优先级。在fig.override-none=false的情况下,外部源配置也⽐本地⽂件拥有更⾼的优先级。
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论