如何在 Spring @Value 注解中正确指定默认值?

Posted

技术标签:

【中文标题】如何在 Spring @Value 注解中正确指定默认值?【英文标题】:How to correctly specify a default value in the Spring @Value annotation? 【发布时间】:2015-01-11 01:17:38 【问题描述】:

最初,我有以下规格:

@Value("#props.isFPL")
private boolean isFPL=false;

这可以正常从属性文件中获取值:

isFPL = true

但是,以下带有默认值的表达式会导致错误:

@Value("#props.isFPL:false")
private boolean isFPL=false;

表达式解析失败;嵌套异常是 org.springframework.expression.spel.SpelParseException: EL1041E:(pos 28): 解析有效表达式后,表达式中还有更多数据:'colon(:)'

我也尝试使用 $ 而不是 #。

@Value("$props.isFPL:true")
private boolean isFPL=false;

然后注释中的默认值可以正常工作,但我没有从属性文件中得到正确的值:

【问题讨论】:

# 是一个表达式,$ 是一个值的占位符。您使用的第一个表达式将在名为 props 的 bean 上调用方法/属性,带有占位符的表达式将尝试在 Environment 中找到名为 props.isFPL 的属性。您应该使用后者,但您可能以错误的方式加载属性。 谢谢。如果我以错误的方式加载属性,为什么 # 会选择正确的值? 因为这是一个表达式而不是占位符。它们都以完全不同的方式进行评估。 【参考方案1】:

尝试使用$,如下所示:

@Value("$props.isFPL:true")
private boolean isFPL=false;

还要确保将ignore-resource-no-found 设置为true,这样如果缺少属性文件,将采用默认 值。

如果使用基于 XML 的配置,请将以下内容放在上下文文件中:

<context:property-placeholder ignore-resource-not-found="true"/>

如果使用 Java 配置:

 @Bean
 public static PropertySourcesPlaceholderConfigurer   propertySourcesPlaceholderConfigurer() 
     PropertySourcesPlaceholderConfigurer p =  new PropertySourcesPlaceholderConfigurer();
     p.setIgnoreResourceNotFound(true);

    return p;
 

【讨论】:

我的 $ 问题不是忽略默认值。问题是属性文件中的值被忽略了 你是如何加载属性文件的?【参考方案2】:

取决于你如何加载你的属性,如果你使用类似的东西

&lt;context:property-placeholder location="classpath*:META-INF/spring/*.properties" /&gt;

那么@Value 应该是这样的

@Value("$isFPL:true")

【讨论】:

【参考方案3】:

您的 Spring 应用程序上下文文件是否包含多个 propertyPlaceholder bean,如下所示:

<context:property-placeholder ignore-resource-not-found="true" ignore-unresolvable="true" location="classpath*:/*.local.properties" />
<context:property-placeholder location="classpath:/config.properties" />

如果是这样,那么属性查找:props.isFPL 将只针对第一个属性文件 (.local.properties),如果没有找到属性,则默认值 (true) 将生效,并且此属性的第二个属性文件 (config.properties) 将被有效地忽略。

【讨论】:

这是自 2012 年以来的一个已知问题,但未修复,显然是由于缺乏兴趣和没有干净的修复方法。请参阅github.com/spring-projects/spring-framework/issues/14623 进行讨论以及一些解决方法。 michelschudel.nl/wp/2017/01/25/… 以通俗易懂的方式解释了它【参考方案4】:

对于int 类型变量:

@Value("$my.int.config: #100")
int myIntConfig;

注意:冒号之前没有空格,而冒号之后有多余的空格。

【讨论】:

我认为不需要额外的空格(冒号后)。 似乎是旧答案。我能够像任何其他值一样映射 int 值。 @Value("$my.int.config:100")【参考方案5】:

对于字符串,您可以像这样默认为 null:

public UrlTester(@Value("$testUrl:") String url) 
    this.url = url;

【讨论】:

从维护的角度来看,我宁愿看到@Value("$testUrl:#null") 这似乎是错误的。对于 String $var: 默认为空 String ""【参考方案6】:

这种定义默认值的方式只有当我们在@Value 注解中写“value=...”时才有效。例如

不起作用 : @Value("$testUrl:some-url" // 无论你在配置文件中做什么,这总是会设置“some-url”。

Works : @Value(value = "$testUrl:some-url" // 仅当配置文件中缺少 testUrl 属性时才会设置“some-url”。

【讨论】:

【参考方案7】:

您问题的确切答案取决于参数的类型

对于“字符串”参数,您的示例代码可以正常工作:

@Value("#props.string.fpl:test")
private String fpl = "test";

对于其他类型(如您问题中的布尔值),它应该这样写:

@Value("$props.boolean.isFPL:#false")
private boolean isFPL = false;

或者对于“整数”:

@Value("$props.integer.fpl:#20")

【讨论】:

以上是关于如何在 Spring @Value 注解中正确指定默认值?的主要内容,如果未能解决你的问题,请参考以下文章

基于注解的Ioc配置 —— Spring

spring基于注解的 IOC 配置

Spring

spring和springboot常用注解总结

spring和springboot常用注解总结

spring boot 入门1-----如何使用@Value注解读取配置文件以及使用@ConfigrationProperties注解