Java 使用 Spring 配置文件设置系统属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3339736/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:25:51  来源:igfitidea点击:

Set System Property With Spring Configuration File

javaspringjunitlog4j

提问by Steve

Configuration:
Spring 2.5, Junit 4, Log4j
The log4j file location is specified from a system property

配置
Spring 2.5、Junit 4、Log4j
log4j 文件位置由系统属性指定

${log.location}

At runtime, system property set with -D java option. All is well.

在运行时,系统属性设置为 -D java 选项。一切都很好。

Problem / What I Need:
At unit test time, system property not set, and file location not resolved.
App uses Spring, would like to simply configure Spring to setthe system property.

问题/我需要什么:
在单元测试时,系统属性未设置,文件位置未解析。
App 使用 Spring,想简单的配置 Spring 来设置系统属性。

More Info:
Requirement is for configuration only. Can't introduce new Java code, or entries into IDE. Ideally, one of Spring's property configuration implementations could handle this--I just haven't been able to find the right combination.

更多信息:
要求仅用于配置。不能引入新的 Java 代码或进入 IDE。理想情况下,Spring 的一个属性配置实现可以处理这个问题——我只是找不到正确的组合。

This idea is close, but needs to add Java code:
Spring SystemPropertyInitializingBean

这个想法很接近,但是需要添加Java代码:
Spring SystemPropertyInitializingBean

Any help out there? Any ideas are appreciated.

有什么帮助吗?任何想法表示赞赏。

采纳答案by Sean Patrick Floyd

You can achieve that with the combination of two MethodInvokingFactoryBeans

您可以通过组合两个MethodInvokingFactoryBeans来实现

Create an inner bean that accesses System.getProperties and an outer bean that invokes putAll on the properties acquired by the inner bean:

创建一个访问 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>

(You could of course use just one bean and target System.setProperties(), but then you'd be replacing existing properties which is not a good idea.

(当然,您可以只使用一个 bean 并以 System.setProperties() 为目标,但是您将替换现有的属性,这不是一个好主意。

Anyway, here's my little test method:

无论如何,这是我的小测试方法:

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"));
}

And here's the output:

这是输出:

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

回答by Patrick

There was a request in the comments for a Spring 3 example on how to do this.

评论中有一个关于如何执行此操作的 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>

回答by paulcm

Spring Batch has a SystemPropertyInitializerclass which can be used to set a system property slightly more concisely, e.g. to force JBoss logging to use slf4j (with Spring JPA):

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"

Remember to add the "depends-on" attribute to force the system property to be set first.

请记住添加“depends-on”属性以强制首先设置系统属性。

回答by Paul Rooney

For a more terse approach try:

对于更简洁的方法,请尝试:

<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'}}"/>