使用 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 并且目标对象行变为<map><entry ... />...</map>
来代替吗?【参考方案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()
显然直到 <context:property-placeholder />
被调用之后才被调用。【参考方案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怎么设置加载顺序