PropertyPlaceholderConfigurer Bean を含む Spring @Configuration ファイルは @Value アノテーションを解決しません 質問する

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。一方PropertyPlaceholderConfigurer、xml ファイルで構成した場合は、すべてが期待どおりに完全に機能します。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 構成ファイルにプロパティ値を挿入しようとすると、適切に挿入されます。Bean のPropertyPlaceholderConfigurer作成をその構成ファイルに移動すると、フィールド値は再び null になります。

回避策として、次のコード行を使用します。

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

これも動作しますが、なぜこのような動作が発生するのか、また、xml を使用せずに別の方法で書き直すことは可能かどうかを知りたいです。

ベストアンサー1

春からJavaドキュメント:

PropertySource のプロパティを使用して定義または @Value アノテーション内の ${...} プレースホルダーを解決するには、PropertySourcesPlaceholderConfigurer を登録する必要があります。これは、XML で context:property-placeholder を使用する場合は自動的に行われますが、@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();
     }
}

2021年9月更新

Koray がコメントで述べたように、 はSpring 4.3+ / Spring Boot 1.5+ 以降では不要になりました。およびアノテーションのプロパティ ファイルには、追加の構成なしでPropertySourcesPlaceholderConfigurer動的ファイル名を使用できます。@PropertySource@ConfigurationProperties

@Configuration
@PropertySource(
          value={"classpath:properties/${property:defaultValue}.properties"},
          ignoreResourceNotFound = true)
public class ConfigExample {

    @Value("${propertyNameFromFile:defaultValue}")
    String propertyToBeInjected;
}
@ConfigurationProperties("properties/${property:defaultValue}.properties")
public class ConfigExample {

    String propertyNameFromFile;
}

おすすめ記事