2015-10-26 75 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類來解決此問題。