带有PropertyPlaceholderConfigurer bean的Spring @Configuration文件无法解析@Value注释

我有以下配置文件:

@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文件示例:

    classpath:properties/${property:defaultValue}.properties   

如果我尝试在另一个Spring配置文件中注入属性值 – 它被正确注入。 如果我将PropertyPlaceholderConfigurer bean创建移动到该配置文件 – 字段值再次为null。

作为解决方法,我使用这行代码:

 System.getProperties().getProperty("property", "defaultValue") 

哪个也有效,但我想知道为什么会出现这种行为,也许有可能以其他方式重写它但没有xml?

来自Spring JavaDoc :

为了使用PropertySource中的属性解析定义中的$ {…}占位符或@Value注释,必须注册PropertySourcesPlaceholderConfigurer。 在XML中使用时会自动发生这种情况,但在使用@Configuration类时必须使用静态@Bean方法显式注册。 有关详细信息和示例,请参阅@Assiguration的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(); } } 

对于任何其他可怜的灵魂,当他们在其他人工作时,他们无法在某些配置类中使用它:

看看你在该类中有哪些其他bean,以及它们中的任何一个是否在ApplicationContext的早期实例化。 ConversionService就是一个例子。 这将在注册所需内容之前实例化Configuration类,从而不会发生属性注入。

我通过将ConversionService移动到我导入的另一个Configuration类来修复此问题。

如果使用VM选项运行应用程序,然后想要在应用程序中访问该选项,则必须执行稍微不同的操作:

 @Value("#{systemProperties.property}") private String property; 

您的PropertyPlaceholderConfigurer不知道系统属性,还要注意您使用$访问属性 – 这是指占位符, #是指bean,其中systemProperties是bean。