有一个行为我找不到相关的留档。让我们假设以下代码。它应该在控制台中显示使用foo.bar属性配置的内容:
@SpringBootApplication
@Component
public class Test {
@Autowired
TestConfig testConfig;
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext run = new SpringApplication(Test.class).run(args);
Test test = run.getBean(Test.class);
test.run();
}
public void run() throws Exception {
testConfig.getBar().entrySet().forEach(e -> {
System.out.println(e.getKey() + " " + e.getValue());
});
}
@Configuration
@ConfigurationProperties(ignoreUnknownFields = false, prefix = "foo")
static class TestConfig {
private Map<SomeEnum, String> bar = new HashMap<>();
public Map<SomeEnum, String> getBar() {
return bar;
}
public void setBar(Map<SomeEnum, String> bar) {
this.bar = bar;
}
}
}
如果您在application.yml(foo.bar[A_VALUE]: fromapplication.yml
)中设置了以下属性,它将被正确地拾取并在控制台中显示“fromapplication.yml”,没什么花哨的
现在,如果您使用完全相同的代码,但这次您想使用命令行参数覆盖application.yml中定义的属性,并将--foo.bar[aValue]="from命令行"
设置为命令行arg(请注意,这次我使用骆驼大小写作为枚举引用)。它仍然在控制台中显示"fromapplication.yml",而不是覆盖的属性。
如果我在命令行中选择大写枚举,在application.yml中选择骆驼大写枚举,它仍然会向控制台显示相同的内容。
这是预期的行为吗?在这种情况下的规则是什么?
根据我的测试,它与https://docs . spring . io/spring-boot/docs/current/reference/html/boot-features-external-config . html # boot-features-external-config中描述的完全相反
我已经用Spring启动 1.2.5.发布和 1.3.0.发布进行了测试
谢谢你的时间
在配置属性中,最后一个获胜:
>
应用程序。yaml(1)
foo.bar.A_VALUE : 111
foo.bar.aValue : 222 # output '222', overrieded
应用程序. yaml (2)
foo.bar.aValue : 222
foo.bar.A_VALUE : 111 # output '111', overrieded
因此,当在PropertiesConfigurationFactory#doBindProperties ToTarget()(我使用的是spring boot 1.5.2)进行调试时,使用:
>
-Dfoo.bar.B_VALUE=b11-Dfoo.bar.cValue=c11
application.yml:
foo.bar:
A_VALUE: aaa
B_VALUE: bbb
C_VALUE: ccc
D_VALUE: dddd
dValue: ddd
logging.level:
org.springframework.boot.env: TRACE
org.springframework.boot.context.config: DEBUG
propertyValues#propertyValues 这是 LinkedHashMap,具有以下属性键顺序:
// keys are unique, when same key, systemProperties take first.
0. `foo.bar.B_VALUE` from 'systemProperties'
1. `foo.bar.cValue` from 'systemProperties'
2. `foo.bar.A_VALUE` from 'applicationConfig: [classpath:/application.yml]'
3. `foo.bar.C_VALUE` from 'applicationConfig: [classpath:/application.yml]'
4. `foo.bar.D_VALUE` from 'applicationConfig: [classpath:/application.yml]'
5. `foo.bar.dValue` from 'applicationConfig: [classpath:/application.yml]'
控制台输出为:
B_VALUE b11 // systemProperties first
A_VALUE aaa
D_VALUE ddd // the last one wins. (foo.bar.dValue)
C_VALUE ccc // ths last one wins. (foo.bar.C_VALUE)
在我的测试中,使用JSON符号:
PropertiesConfigurationFactory#propertySources = {
class : ConfigurationPropertiesBindingPostProcessor$FlatPropertySources
propertySources : [ {
class : PropertySourcesPlaceholderConfigurer$1
name : 'environmentProperties',
source: {
class : StandardServletEnvironment,
propertySource : {
class : MutablePropertySources,
propertySourceList : [{
class: PropertySource$StubPropertySource,
name : 'servletConfigInitParams'
}, {
class: MapPropertySource,
name : 'systemProperties'
}, {
class: SystemEnvironmentPropertySource,
name : 'systemEnvironment'
}, {
class: RandomValuePropertySource,
name : 'random'
}, {
class: MapPropertySource,
name : 'applicationConfig: [classpath:/application.yml]'
}, {
class: MapPropertySource,
name : 'refresh'
}]
}
}
}, {
class : PropertiesPropertySource,
name : 'localProperties',
source: <Properties> // empty in my test
}]
}
注意:类<code>PropertiesConfigurationFactory</code>已在spring boot 2.x中删除。
PS:当搜索这个问题时,我想弄清楚Enum值(如A_VALUE)可以写入配置属性中的概念。答案正如@Moit所说。
RelaxedDataBinder#bind()
RelaxedConversionService#convert()
1. try DefaultConvertionService#convert()
# only support `A_VALUE`
StringToEnumConverterFactory#StringToEnum#convert()
2. then GenericConversionService#convert()
# the config key can be :
# 0 = "a-value"
# 1 = "a_value"
# 2 = "aValue"
# 3 = "avalue"
# 4 = "A-VALUE"
# 5 = "A_VALUE"
# 6 = "AVALUE"
RelaxedConversionService$StringToEnumIgnoringCaseConverterFactory$StringToEnum#convert()
Spring使用StringToEnum
将字符串值转换为枚举。该类在内部使用java.lang.Enum#valueOf
方法进行转换。枚举类创建一个映射,然后在此映射上执行查找。因此,密钥必须与查找成功的确切大小写匹配。
以下测试用例将验证:
enum SomeEnum{
A, B
}
public class EnumTest {
public static void main(String[] args) {
SomeEnum e1 = Enum.valueOf(SomeEnum.class, "A");
System.out.println(e1);
SomeEnum e2 = Enum.valueOf(SomeEnum.class, "a"); //throws exception
}
}
因此,当spring无法转换从命令行传递的值时,它会返回到application.yml中定义的值。
编辑
如果您尝试以下组合:
foo.bar[A_VALUE]: from application.yml
foo.bar[A_VALUE]: from command line
{A_VALUE=from command line}
foo.bar[A_VALUE]: from application.yml
foo.bar[aValue]: from command line
{A_VALUE=from application.yml}
foo.bar[aValue]: from application.yml
foo.bar[A_VALUE]: from command line
{A_VALUE=from application.yml}
foo.bar[aValue]: from application.yml
foo.bar[aValue]: from command line
{A_VALUE=from command line}
第一
第二
问题内容: 我的应用程序需要使用.properties文件进行配置。在属性文件中,允许用户指定路径。 问题 属性文件需要转义的值,例如 需要的 我需要某种方法来接受不转义值的属性文件,以便用户可以指定: 问题答案: 为什么不简单地扩展属性类以合并双正斜杠的剥离。这样做的一个好功能是,在程序的其余部分中,您仍然可以使用原始类。 使用新类很简单: 剥离代码也可以进行改进,但是总的原理就在那里。
问题内容: 我定义了一个独立的枚举类型,如下所示: 现在,我想将该类型的值注入bean属性: …那行不通:( 我应该如何将枚举注入spring bean? 问题答案: 你是否尝试过“ TYPE1”?我想Spring还是要使用反射来确定“类型”的类型,因此完全限定的名称是多余的。Spring通常不接受冗余!
问题内容: 我正在使用不同的Maven配置文件将我的应用程序部署到不同的环境。(使用weblogic-maven-plugin,但是我认为这并不重要) 在应用程序中,我使用Spring Web Services。现在,我想根据环境更改端点。(端点在Spring的applicationContext.xml中定义) 我的想法是从属性文件中读取值。该属性文件将在Mavens软件包阶段写入(或复制)。
问题内容: 我有一个定义自己的枚举的类,如下所示: 如果指定MyEnum.E1,它可以正常工作,但我真的很想将其作为“ E1”。您知道如何实现此目的,还是必须在另一个文件中定义它才能起作用? 结论:我无法正确获取导入的语法。由于有几个答案表明这是可能的,因此我将选择一个为我提供所需语法的文件,并对其他文件进行投票。 顺便说一下,这是一个真正的STRANGE部分(在我执行静态导入之前),我编写的使用
我使用下面的代码(来自这个答案)来配置要记录在WebClient请求上的头: 这很管用,但感觉有点奇怪。问题是:我是否需要像这样包含Jackson/objectMapper配置,或者是否有更简单的方法来避免Spring objectMapper配置被覆盖?
我希望将concur严格用作配置源。我正在使用spring cloud Consor配置来获取配置。我正在使用git2consul将文件加载到Consor并读取它们。根据spring云文档,我在构建中添加了以下内容。格拉德尔 并在我的application.properties 我面临的问题是,预期的属性没有加载到ConfigurationProperties bean中。在ConsultProp