我有以下配置文件:
@Configuration
public class PropertyPlaceholderConfigurerConfig {
@Value("${property:defaultValue}")
private String property;
@Bean
public static PropertyPlaceholderConfigurer ppc() throws IOException {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setLocations(new ClassPathResource("properties/" + property + ".properties"));
ppc.setIgnoreUnresolvablePlaceholders(true);
return ppc;
}
}
我使用以下VM选项运行我的应用程序:
-Dproperty=propertyValue
所以我希望我的应用程序在启动时加载特定的属性文件。但由于某些原因,在此阶段@Value
注释未被处理且属性为null
。另一方面,如果我通过xml文件配置PropertyPlaceholderConfigurer
- 一切都按预期完美运行。 Xml文件示例:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true"/>
<property name="location">
<value>classpath:properties/${property:defaultValue}.properties</value>
</property>
</bean>
如果我尝试在另一个Spring配置文件中注入属性值 - 它会被正确注入。如果我将PropertyPlaceholderConfigurer
bean创建移动到该配置文件 - 字段值再次为null。
作为解决方法,我使用以下代码:
System.getProperties().getProperty("property", "defaultValue")
哪个也有效,但我想知道为什么会发生这种行为,也许有可能以其他方式重写它但没有xml?
答案 0 :(得分:38)
从春天JavaDoc:
为了使用PropertySource中的属性解析定义中的$ {...}占位符或@Value注释,必须注册PropertySourcesPlaceholderConfigurer。在XML中使用时会自动发生这种情况,但在使用@Configuration类时必须使用静态@Bean方法显式注册。有关详细信息和示例,请参阅@Conit的javadoc的“使用外部化值”部分和@ Bean的javadoc的“关于BeanFactoryPostProcessor返回@Bean方法的注释”。
因此,您尝试在启用占位符处理所需的代码块中使用占位符。
正如@ M.Deinum所提到的,你应该使用PropertySource(默认或自定义实现)。
下面的示例显示了如何在PropertySource注释中使用属性以及如何在字段中从PropertySource注入属性。
@Configuration
@PropertySource(
value={"classpath:properties/${property:defaultValue}.properties"},
ignoreResourceNotFound = true)
public class ConfigExample {
@Value("${propertyNameFromFile:defaultValue}")
String propertyToBeInjected;
/**
* Property placeholder configurer needed to process @Value annotations
*/
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
答案 1 :(得分:6)
对于任何其他可怜的灵魂,当他们在其他人中工作时,他们无法在某些配置类中使用它:
查看该类中有哪些其他bean,以及它们中的任何一个是否在ApplicationContext中尽早实例化。 ConversionService就是一个例子。这将在注册所需内容之前实例化Configuration类,从而不会进行属性注入。
我通过将ConversionService移动到我导入的另一个Configuration类来修复此问题。
答案 2 :(得分:2)
如果您使用VM选项运行应用程序,然后想要在您的应用程序中访问该选项,则必须略有不同:
@Value("#{systemProperties.property}")
private String property;
您的PropertyPlaceholderConfigurer不知道系统属性,还要注意您使用$
访问属性 - 它引用占位符而#
引用bean,其中systemProperties
是bean