web-dev-qa-db-ja.com

Spring構成ファイルでシステムプロパティを設定する

構成
Spring 2.5、Junit 4、Log4j
log4jファイルの場所は、システムプロパティから指定されます

${log.location}

実行時に、システムプロパティは-D Javaオプションで設定されます。すべて順調です。

問題/必要なもの:
単体テスト時に、システムプロパティが設定されず、ファイルの場所が解決されません。
アプリはSpringを使用します。システムプロパティをsetに設定するだけです。

詳細:
要件は設定専用です。新しいJavaコード、またはIDEへのエントリを導入できません。理想的には、Springのプロパティ構成実装の1​​つがこれを処理できます。適切な組み合わせを見つけることができませんでした。

このアイデアは近いですが、Javaコードを追加する必要があります:
Spring SystemPropertyInitializingBean

助けがありますか?どんなアイデアでも大歓迎です。

56
Steve

これは、2つの組み合わせ MethodInvokingFactoryBeans で実現できます。

System.getPropertiesにアクセスする内部Beanと、内部Beanによって取得されたプロパティでputAllを呼び出す外部Beanを作成します。

<bean
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property
        name="targetObject">
        <!-- System.getProperties() -->
        <bean
            class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
            <property name="targetClass" value="Java.lang.System" />
            <property name="targetMethod" value="getProperties" />
        </bean>
    </property>
    <property
        name="targetMethod"
        value="putAll" />
    <property
        name="arguments">
        <!-- The new Properties -->
        <util:properties>
            <prop
                key="my.key">myvalue</prop>
            <prop
                key="my.key2">myvalue2</prop>
            <prop
                key="my.key3">myvalue3</prop>

        </util:properties>
    </property>
</bean>

(もちろん、1つのBeanのみを使用してSystem.setProperties()をターゲットにすることもできますが、既存のプロパティを置き換えることになりますが、これはお勧めできません。

とにかく、ここに私の小さなテスト方法があります:

public static void main(final String[] args) {

    new ClassPathXmlApplicationContext("classpath:beans.xml");

    System.out.println("my.key: "+System.getProperty("my.key"));
    System.out.println("my.key2: "+System.getProperty("my.key2"));
    System.out.println("my.key3: "+System.getProperty("my.key3"));

    // to test that we're not overwriting existing properties
    System.out.println("Java.io.tmpdir: "+System.getProperty("Java.io.tmpdir"));
}

出力は次のとおりです。

my.key: myvalue
my.key2: myvalue2
my.key3: myvalue3
Java.io.tmpdir: C:\DOKUME~1\SEANFL~1\LOKALE~1\Temp\
55

これを行う方法に関するSpring 3の例のコメントにリクエストがありました。

<bean id="systemPrereqs"
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" value="#{@systemProperties}" />
    <property name="targetMethod" value="putAll" />
    <property name="arguments">
        <!-- The new Properties -->
        <util:properties>
            <prop key="Java.security.auth.login.config">/super/secret/jaas.conf</prop>
        </util:properties>
    </property>
</bean>
92
Patrick

Spring Batchには SystemPropertyInitializer クラスがあり、これを使用してシステムプロパティをより簡潔に設定できます。 JBossロギングでslf4jを強制的に使用するには(Spring JPAを使用):

<bean id="setupJBossLoggingProperty"
    class="org.springframework.batch.support.SystemPropertyInitializer"
    p:keyName="org.jboss.logging.provider" p:defaultValue="slf4j"/>

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    depends-on="setupJBossLoggingProperty"

「depends-on」属性を追加して、システムプロパティを最初に強制設定することを忘れないでください。

10
paulcm

より簡潔なアプローチを試すには:

<beans ... xmlns:p="http://www.springframework.org/schema/p" ...    
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" 
        p:targetObject="#{@systemProperties}" p:targetMethod="setProperty"
        p:arguments="#{{'org.jboss.logging.provider','slf4j'}}"/>
3
Paul Rooney