次の構成ファイルがあります。
@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を使用せずに他の方法で書き換えることができますか?
Springから JavaDoc :
PropertySourceのプロパティを使用して、定義または@Valueアノテーションの$ {...}プレースホルダーを解決するには、PropertySourcesPlaceholderConfigurerを登録する必要があります。これはXMLで使用すると自動的に発生しますが、@ Configurationクラスを使用する場合は静的な@Beanメソッドを使用して明示的に登録する必要があります。詳細と例については、@ Configurationの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();
}
}
他のクラスで動作するときに、これをいくつかのConfigurationクラスで動作させることができなかった他の貧しい人々のために:
そのクラスにある他のBeanを確認し、それらのBeanのいずれかがApplicationContextの初期にインスタンス化されるかどうかを確認します。 ConversionServiceはその一例です。これにより、必要なものが登録される前にConfigurationクラスがインスタンス化され、プロパティの挿入が行われなくなります。
ConversionServiceをインポートした別の構成クラスに移動することで、これを修正しました。
VMオプションを使用してアプリケーションを実行し、アプリケーションでそのオプションにアクセスする場合は、わずかに異なる操作を行う必要があります。
@Value("#{systemProperties.property}")
private String property;
PropertyPlaceholderConfigurerはシステムプロパティを認識しません。また、$
-プレースホルダーと#
はBeanを指します。systemProperties
はBeanです。