springcloud config配置读取优先级
本文内容纲要:
-情景描述
-springcloudconfig读取仓库配置
-外部源读取优先级
-自定义PropertySourceLocator接口
-小结
情景描述
最近在修复Eureka的静态页面加载不出的缺陷时,最终发现是远程GIT仓库将静态资源访问方式配置给禁用了(spring.resources.add-mappings=false)。虽然最后直接修改远程GIT仓库的此配置项给解决了(spring.resources.add-mappings=true),但是从中牵涉出的配置读取优先级我们必须好好的再回顾下
springcloudconfig读取仓库配置
通过configclient模块来读取远程的仓库配置,只需要在boostrap.properties文件中配置如下属性即可
spring.application.name=eureka
spring.cloud.config.uri=http://localhost:8888
spring.cloud.config.name=dev
spring.cloud.config.username=dev
spring.cloud.config.password=dev
其就会以GET方式去请求*http://localhost:8888/eureka/dev*地址从而将配置拉取下来。
当然上述的API地址也是需要被访问服务器部署了configserver服务方可调用,具体的细节就不展开了
外部源读取优先级
我们都知道spring的配置属性管理均是存放在Enviroment对象中,就以普通项目StandardEnvironment
为例,其配置的存放顺序可罗列如下
那么远程读取的配置的存放应该放在上述的哪个位置呢?
我们都知道boostrap上下文通过暴露org.springframework.cloud.bootstrap.config.PropertySourceLocator接口来方便集成第三方的外部源配置读取,比如本文提及的configclient模块中的org.springframework.cloud.config.client.ConfigServicePropertySourceLocator实现类。
但最终将外部源配置读取以及插入至Environment对象中则是通过org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration类来完成的。
PropertySourceBootstrapConfiguration
此类也是ApplicationContextInitializer接口的实现类,阅读过cloud源码的都知道,此类被调用是在子类上下文初始化的时候,我们主要看下其复写的initialize()方法
@Override
publicvoidinitialize(ConfigurableApplicationContextapplicationContext){
CompositePropertySourcecomposite=newCompositePropertySource(
BOOTSTRAP_PROPERTY_SOURCE_NAME);
//对在boostrap上下文类型为PropertySourceLocator的bean集合进行排序
AnnotationAwareOrderComparator.sort(this.propertySourceLocators);
booleanempty=true;
ConfigurableEnvironmentenvironment=applicationContext.getEnvironment();
for(PropertySourceLocatorlocator:this.propertySourceLocators){
PropertySource<?>source=null;
//读取外部配置源
source=locator.locate(environment);
if(source==null){
continue;
}
logger.info("Locatedpropertysource:"+source);
composite.addPropertySource(source);
empty=false;
}
if(!empty){
MutablePropertySourcespropertySources=environment.getPropertySources();
StringlogConfig=environment.resolvePlaceholders("${logging.config:}");
LogFilelogFile=LogFile.get(environment);
if(propertySources.contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)){
propertySources.remove(BOOTSTRAP_PROPERTY_SOURCE_NAME);
}
//插入至Environment环境对象中
insertPropertySources(propertySources,composite);
reinitializeLoggingSystem(environment,logConfig,logFile);
setLogLevels(applicationContext,environment);
handleIncludedProfiles(environment);
}
}
直接观察对应的*insertPropertySources()*方法
privatevoidinsertPropertySources(MutablePropertySourcespropertySources,
CompositePropertySourcecomposite){
//外部源配置集合
MutablePropertySourcesincoming=newMutablePropertySources();
incoming.addFirst(composite);
PropertySourceBootstrapPropertiesremoteProperties=newPropertySourceBootstrapProperties();
//从外部源配置源集合中读取PropertySourceBootstrapProperties的相关属性
//例如spring.cloud.config.overrideSystemProperties等属性
Binder.get(environment(incoming)).bind("spring.cloud.config",
Bindable.ofInstance(remoteProperties));
//spring.cloud.config.allow-override=false或者spring.cloud.config.override-none=false且spring.cloud.config.override-system-properties=true
if(!remoteProperties.isAllowOverride()||(!remoteProperties.isOverrideNone()
&&remoteProperties.isOverrideSystemProperties())){
propertySources.addFirst(composite);
return;
}
//spring.cloud.config.override-none=true则处于最低读取位
if(remoteProperties.isOverrideNone()){
propertySources.addLast(composite);
return;
}
//根据spring.cloud.config.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实体类中,且其中的默认值罗列如下
2.针对相应的属性的值对应的外部源在Environment对象中的读取优先级,罗列如下
即默认情况下,外部源的配置属性的读取优先级是最高的。
且除了spring.cloud.config.override-none=true的情况下,其他情况下外部源的读取优先级均比本地配置文件高。
**Note:**值得注意的是,如果用户想复写上述的属性,则放在bootstrap.yml|application.yml配置文件中是无效的,根据源码分析只能是自定义一个PropertySourceLocator接口实现类并放置在相应的spring.factories文件中方可生效。
自定义PropertySourceLocator接口
针对上文描述,假设有这么一个场景,远程仓库的配置都是公有的,我们也不能修改它,我们只在项目中去复写相应的配置以达到兼容的目的。那么用户就需要自定义去编写接口了
1.编写PropertySourceLocator接口实现类
packagecom.example.configdemo.propertysource;
importorg.springframework.cloud.bootstrap.config.PropertySourceLocator;
importorg.springframework.core.Ordered;
importorg.springframework.core.annotation.Order;
importorg.springframework.core.env.Environment;
importorg.springframework.core.env.MapPropertySource;
importorg.springframework.core.env.PropertySource;
importjava.util.HashMap;
importjava.util.Map;
/**
*@authornanco
*@create19/9/22
*@description自定义的PropertySourceLocator的顺序应该要比远程仓库读取方式要优先
*@seeorg.springframework.cloud.config.client.ConfigServicePropertySourceLocator
*/
@Order(value=Ordered.HIGHEST_PRECEDENCE+1)
publicclassCustomPropertySourceLocatorimplementsPropertySourceLocator{
privatestaticfinalStringOVERRIDE_ADD_MAPPING="spring.resources.add-mappings";
@Override
publicPropertySource<?>locate(Environmentenvironment){
Map<String,Object>customMap=newHashMap<>(2);
//远程仓库此配置为false,本地进行复写
customMap.put(OVERRIDE_ADD_MAPPING,"true");
returnnewMapPropertySource("custom",customMap);
}
}
2.编写BootstrapConfiguration
packagecom.example.configdemo.propertysource;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
/**
*@authornanco
*@create19/9/22
*/
@Configuration
publicclassCustomBootstrapConfiguration{
@Bean("customPropertySourceLocator")
publicCustomPropertySourceLocatorpropertySourceLocator(){
returnnewCustomPropertySourceLocator();
}
}
3.在src\main\resources目录下创建META-INF\spring.factories文件
#Bootstrapcomponents
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.example.configdemo.propertysource.CustomBootstrapConfiguration
4.运行main函数即可
小结
默认情况下,外部源配置拥有最高的优先级。在spring.cloud.config.override-none=false的情况下,外部源配置也比本地文件拥有更高的优先级。
本文内容总结:情景描述,springcloudconfig读取仓库配置,外部源读取优先级,自定义PropertySourceLocator接口,小结,
原文链接:https://www.cnblogs.com/question-sky/p/11580365.html