Установить системное свойство с помощью Spring файла конфигурации
Конфигурация:
Spring 2.5, Junit 4, Log4j
Расположение файла log4j указано из системного свойства
${log.location}
Во время выполнения системное свойство задается с параметром -D java. Все хорошо.
Проблема/что мне нужно:
В unit test время системное свойство не задано и местоположение файла не разрешено.
Приложение использует Spring, хотел бы просто настроить Spring на установить системное свойство.
Дополнительная информация:
Требование только для конфигурации. Невозможно ввести новый Java-код или записи в IDE. В идеале одна из реализаций конфигурации свойств Spring могла бы справиться с этим - я просто не смог найти нужную комбинацию.
Эта идея близка, но нужно добавить код Java:
Spring SystemPropertyInitializingBean
Любая помощь там? Любые идеи приветствуются.
Ответы
Ответ 1
Вы можете добиться этого с помощью комбинации MethodInvokingFactoryBeans
Создайте внутренний bean, который обращается к System.getProperties и внешнему 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\
Ответ 2
В комментариях к примеру 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>
Ответ 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"
Не забудьте добавить атрибут "зависит от", чтобы принудительно установить свойство системы.
Ответ 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'}}"/>