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

Posted

技术标签:

【中文标题】使用 Spring 配置文件设置系统属性【英文标题】:Set System Property With Spring Configuration File 【发布时间】:2011-03-21 08:44:21 【问题描述】:

配置: Spring 2.5、Junit 4、Log4j log4j 文件位置是从系统属性中指定的

$log.location

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

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

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

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

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

【问题讨论】:

相关问题及其他答案:***.com/questions/11306951/… 【参考方案1】:

你可以通过两个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>

(您当然可以只使用一个 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\

【讨论】:

谢谢。这行得通。剩下的问题:似乎 log4j 在另一个 bean 中初始化,该 bean 在这些新系统属性初始化之前加载。现在我要弄清楚如何强制对 bean 初始化进行排序。 使用 Spring 的依赖属性。非常感谢您的回答...它是纯金... Spring 3 通过消除对第二个 MethodInvokingFactoryBean 的需要简化了这一点。您使用 SpEL 并且目标对象行变为 @Patrick - 我非常感谢 Spring 3 的一个例子。我从来没有从上面的例子和你的评论中弄清楚如何让它工作。 这需要 util 命名空间。难道不能用更便携的&lt;map&gt;&lt;entry ... /&gt;...&lt;/map&gt; 来代替吗?【参考方案2】:

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

【讨论】:

+1 非常好。当我想到需要编写多少代码才能做到这一点时。有时春天是神奇的。 :-) 你会如何加载这个?我只是声明一个 MethodInvokingFactoryBean 类型的 @Autowired 变量 @Patrick 仍然没有在 log4j 系统 prop 示例中设置。如果使用 -Dcatalina.base=target 完成,则在使用 SpringJUnit4ClassRunner 运行时在 log4j 工具之前进行此初始化有什么特别的吗?谢谢。 @JosephLust 要处理这个文件,Spring 必须启动,它会在启动时记录一些内容,从而初始化 log4j,因此 log4j 永远不会看到您的设置。您可以尝试在 Spring 处理文件时重新初始化 log4j - 可能调用 PropertyConfigurator.configure(URL configURL)【参考方案3】:

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”属性强制先设置系统属性。

【讨论】:

我最终无法让它工作。 SystemPropertyInitializer 使用 afterPropertiesSet() 显然直到 &lt;context:property-placeholder /&gt; 被调用之后才被调用。【参考方案4】:

如需更简洁的方法,请尝试:

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

【讨论】:

以上是关于使用 Spring 配置文件设置系统属性的主要内容,如果未能解决你的问题,请参考以下文章

spring boot importsource怎么设置加载顺序

01Spring Boot配置文件相关

如何从系统变量设置 Spring 配置文件?

如何根据 Spring Boot 中的活动配置文件设置注释属性值?

spring 使用外部属性文件

Spring-Bean配置-使用外部属性文件(转)