2015-10-26 31 views
15

我有以下的配置文件:春@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文件示例:

<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创建移动到该配置文件 - 字段值再次为空。

至于解决方法,我用这行代码:

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

这也是工作,但我想知道为什么这样的行为发生,也许有可能改写其他方式,但没有XML?

+1

首先,我强烈建议使用'ProperySourcesPlaceholderConfigurer'并在您的课堂上使用'@ PropertySource'。其次,这个bean需要是“静态”的。 –

+0

@ M.Deinum'@ PropertySource'对我来说非常完美,但是如果我有自定义的'ProperySourcesPlaceholderConfigurer'实现呢? –

+0

为什么你需要一个自定义的实现。 –

回答

30

从春天JavaDoc

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

如果您在使用VM选项运行你的应用程序,然后要访问您的应用程序选项,你必须这样做略有不同:

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

你PropertyPlaceholderConfigurer不知道系统的性能,还要注意你正在使用$访问属性 - 这是指占位符,#是指豆,其中systemProperties是一个bean。

+0

不幸的是,它在配置中无法使用PropertyPlaceholderConfigurer bean创建,但适用于任何另一个配置文件 –

3

对于其他任何可怜的灵魂谁也不能得到这个在一些配置类的工作时,他们在别人的工作:

看看,看看你有该类什么其他豆类,如果任何人在ApplicationContext的早期实例化。 ConversionService就是一个例子。这将在需要注册之前实例化Configuration类,从而不会发生属性注入。

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