使用SpEL在Spring @Value注释中遇到一个有趣的问题。设置null的默认值适用于String变量。但是,对于Set变量,它不会。
所以,这可行(varStr为null):
@Value("${var.string:#{NULL}}")
private String varStr;
虽然这不是(varSet现在包含一个元素"#{NULL}"):
@Value("#{'${var.set:#{NULL}}'.split(',')}")
private Set<String> varSet;
问题是如何使用Set变量使其工作,因此默认情况下它将设置为null。
非常感谢您的帮助。
答案 0 :(得分:4)
您可以尝试将@Value
注入数组而不是Set。然后在@PostConstruct
init块中将其转换为所需的Set实例。当没有这样的属性时,Spring似乎注入了一个空数组(非空)(注意@Value
字符串中的空默认值)。当它存在时,默认情况下会以逗号分割。
像这样:
@Value("${some.prop:}")
private String[] propsArr;
private Set<String> props;
@PostConstruct
private void init() throws Exception {
props = (propsArr.length == 0) ? null : Sets.newHashSet(propsArr);
}
我将提出另一个建议。我建议您根本不使用null
,而是使用空的Set。 Null往往容易出错,并且通常不会传达任何比空集合更多的信息。您的情况可能会有所不同 - 这只是一般性建议。
BTW - Sets.newHashSet(...)
来自Google's Guava library。强烈推荐。
答案 1 :(得分:2)
您可以创建PropertySourcesPlaceholderConfigurer。此bean将拦截属性源值并允许您配置它们。
@Configuration
@ComponentScan
class ApplicationConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
PropertySourcesPlaceholderConfigurer c = new PropertySourcesPlaceholderConfigurer();
c.setNullValue("");
return c;
}
参考:http://blog.codeleak.pl/2015/09/placeholders-support-in-value.html
将空字符串默认为null。
答案 2 :(得分:0)
除非您能找到一个优雅的解决方案来解决这个问题,否则您可以将该属性作为String
注入您的构造函数,然后自己Split()
或默认为null
。
class Foo {
private Set<String> varSet;
public Foo(@Value("${var.string:#{NULL}}") String varString) {
varSet = (varString == null) ? null : new HashSet<>(Arrays.asList(varString.split(",")));
}
}