web-dev-qa-db-ja.com

.propertiesファイルのプロパティに基づいてSpring構成ファイルをインポートする

私のSpring xml構成では、次のようなものを機能させようとしています:

<beans>

   <import resource="${file.to.import}" />

   <!-- Other bean definitions -->

</beans>

プロパティファイルのプロパティに基づいて、インポートするファイルを決定します。システムプロパティを使用できることはわかっていますが、起動時にJVMにプロパティを追加できません。

注:PropertyPlaceHolderConfigurerはnotで機能します。インポートは、BeanFactoryPostProcessorsが実行される前に解決されます。 import要素は、System.propertiesのみを解決できます。

誰かがこれに対する簡単な解決策を持っていますか?フレームワーククラスなどのサブクラス化を開始したくない...

ありがとう

34
nash2000

残念ながら、これは本来あるべきことよりもはるかに困難です。私のアプリケーションでは、次のようにしてこれを実現しました。

  1. PropertyPlaceholderConfigurer Beanとアプリケーションコンテキストのブートストラップを担当する別のBeanのロードを担当する小さな「ブートストラップ」コンテキスト。

  2. 上記の2番目のBeanは、ロードする「実際の」Springコンテキストファイルを入力として受け取ります。構成可能なパーツがよく知られている同じ場所にあるように、Springコンテキストファイルを整理しています。たとえば、3つの構成ファイルがあるとします:one.onpremise.xml、one.hosted.xml、one.multitenant.xml。 Beanはこれらのコンテキストファイルをプログラムで現在のアプリケーションコンテキストにロードします。

これが機能するのは、コンテキストファイルが、それらをロードするBeanの入力として指定されているためです。先ほど述べたように、インポートを試みただけでは機能しませんが、同じ効果が得られますが、少し作業が増えます。 bootstrapクラスは次のようになります:

 public class Bootstrapper implements ApplicationContextAware, InitializingBean {

    private WebApplicationContext context;
    private String[] configLocations;
    private String[] testConfigLocations;
    private boolean loadTestConfigurations;

    public void setConfigLocations(final String[] configLocations) {
        this.configLocations = configLocations;
    }

    public void setTestConfigLocations(final String[] testConfigLocations) {
        this.testConfigLocations = testConfigLocations;
    }

    public void setLoadTestConfigurations(final boolean loadTestConfigurations) {
        this.loadTestConfigurations = loadTestConfigurations;
    }

    @Override
    public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
        context = (WebApplicationContext) applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        String[] configsToLoad = configLocations;

        if (loadTestConfigurations) {
            configsToLoad = new String[configLocations.length + testConfigLocations.length];
            arraycopy(configLocations, 0, configsToLoad, 0, configLocations.length);
            arraycopy(testConfigLocations, 0, configsToLoad, configLocations.length, testConfigLocations.length);
        }

        context.setConfigLocations(configsToLoad);
        context.refresh();
    }
}

基本的に、アプリケーションコンテキストを取得し、構成の場所を設定し、それ自体を更新するように指示します。これは私のアプリケーションで完全に機能します。

お役に立てれば。

15
Louis Marascio

Spring 2.5および3.0の場合、- 同様の解決策があります からルイスへ、しかし3.1の次の機能について読んだところです プロパティ管理 、これも素晴らしい音です。

6
István

Spring JIRAには、追加用の古い問題があります インポートのプロパティプレースホルダーサポート(SPR-1358) 「修正されません」として解決されましたが、EagerPropertyPlaceholderConfigurerを使用した解決策が提案されています。

私はSPR-1358を再開するようロビー活動をしてきましたが、これまでのところ応答はありません。おそらく、他の人が問題のコメントに彼らのユースケースを追加した場合、それは認識を高めるのに役立ちます。

5
Ian Brandt

何故なの:

  1. 起動時にプロパティファイルを読み取る
  2. ロードするSpring構成を決定します
  3. 読み込まれているSpring構成のいずれかが特定のものを設定しますthenは一般的なSpring構成を読み込みます

そのため、現在提案されているソリューションを効果的に反転させています。

2
Brian Agnew

次のようなものを追加します。

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreResourceNotFound"><value>true</value></property>
    <property name="locations">
        <list>
            <value>classpath:propertyfile.properties</value>
        </list>
    </property>
</bean>
1
laz

インポートしたXMLファイルパスの構成を失わずにapplicationContext.xmlを置き換えることができるように、applicationContext.xmlの外部でインポートしたXMLファイル名を指定する場合は、中間のSpring Bean XMLファイル(たとえば、confSelector)を追加するだけです。 xml。これにより、applicationContext.xmlはconfSelector.xmlをインポートし、confSelector.xmlには適切なカスタムBean XMLファイルを参照する<import>要素のみが含まれます。

XMLエンティティ(XMLの先頭にあるDTD宣言に<!ENTITY ...>要素を追加することによって定義される)が役立つかもしれないもう1つの手段です。これらにより、他のファイルからXMLフラグメントをインポートでき、XMLファイルに「プロパティプレースホルダー」のような機能を提供します。

ただし、これらのソリューションでは、構成ファイルをJavaの.properties形式にすることはできません。

1
Jaan

システムプロパティに依存しない別の回避策は、ファイルごとに異なるPropertyPlaceholderConfigurerを使用してすべてのファイルのプロパティを読み込み、ファイルごとに異なるplaceholderPrefixを定義することです。最初のプロパティファイルによって構成されているそのプレースホルダープレフィックス。



最初のプロパティファイルを定義:(最初または2番目のいずれかを含む)

global.properties

fileToUse=first


直前に定義したプロパティに応じて切り替えることができるプロパティを含むファイルを定義します。

first.properties

aProperty=propertyContentOfFirst

second.properties

aProperty=propertyContentOfSecond


次に、すべてのファイルのプレースホルダーを定義します。

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:global.properties</value>
        </list>
    </property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="placeholderPrefix" value="first{" />
    <property name="locations">
        <list>
            <value>classpath:first.properties</value>
        </list>
    </property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="placeholderPrefix" value="second{" />
    <property name="locations">
        <list>
            <value>classpath:second.properties</value>
        </list>
    </property>
</bean>


グローバルで定義されたプロパティを使用して、他のファイルから使用するリソースを識別します:

${fileToUse}{aProperty}
0
Antoine Meyer

以下にJVM引数を追加し、ファイルmyApplicationContext.dev.xmlがある場合、Springはロードされます

-DmyEnvironment = dev

<context:property-placeholder />

<import resource="classpath:/resources/spring/myApplicationContext.${myEnvironment}.xml"/>
0
gabbon

AndréSchusterが答えた答えは、自分のホストで実行しているか、Jenkinsによってビルドホストで実行しているか、または「実際の」デプロイメントで実行しているかに応じて、プロパティの異なる表現を見つけたいという非常に類似した問題を解決するのに役立ちました。これは私がしました:

<context:property-placeholder location="file:///etc/myplace/database.properties" />

後に続く

<bean id="propertyConfigurer"
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>WEB-INF/classes/resources/database.properties</value>
            ...
        </list>
    </property>
</bean>

私の開発ホストでは、/ etc/myplace/database.propertiesdatabase.propertiesの自分のコピーへのリンクを配置したため、問題が解決しましたが、少し異なりますJenkinsを実行しているサーバー上に1つ。実際のデプロイメントでは、そのようなファイルは見つからないため、Springは、クラスファイルのサブディレクトリにあるresourcesの「実際の」ファイルにフォールバックします。問題のプロパティが/ etc/myplace/database.propertiesのファイルで既に指定されている場合、(幸いなことに)ローカルファイルで再定義されません。

0
Russ Bateman