根据this answer,您可以使用Spring Batch类org.springframework.batch.support.SystemPropertyInitializer
在Spring Context启动期间设置系统属性。
特别是,我希望能够使用它来设置ENVIRONMENT
,因为Spring Batch配置的一部分是:
<bean id="placeholderProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/org/springframework/batch/admin/bootstrap/batch.properties</value>
<value>classpath:batch-default.properties</value>
<value>classpath:batch-${ENVIRONMENT:hsql}.properties</value>
</list>
</property>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
<property name="order" value="1" />
</bean>
但是SystemPropertyInitializer
使用afterPropertiesSet()
来设置系统属性,显然在配置PropertyPlaceholderConfigurer
之后会发生。
有可能实现这个目标吗?
答案 0 :(得分:2)
最简单的解决方案是将环境属性作为命令行参数传递,因此可以将其解析为系统属性。
如果这不是一个选项,您可以实现一个ApplicationContextInitializer
,将环境属性提升为系统属性。
public class EnvironmentPropertyInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
boolean override = false; //change if you prefer envionment over command line args
@Override
public void initialize(final ConfigurableApplicationContext applicationContext) {
for (Entry<String, String> environmentProp : System.getenv().entrySet()) {
String key = environmentProp.getKey();
if (override || System.getProperty(key) == null) {
System.setProperty(key, environmentProp.getValue());
}
}
}
}
此处看起来您正在使用Spring Batch Admin,因此您只需添加web.xml
文件即可注册初始值设定项:
<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>org.your.package.EnvironmentPropertyInitializer</param-value>
</context-param>
添加背景,因为评论没有看似充足:这里是相关的类及其调用/评估的顺序。
ApplicationContextInitializer
告诉Spring Application如何加载应用程序上下文,并可用于设置bean配置文件,以及更改上下文的其他方面。这将在完全创建上下文之前执行。PropertyPlaceholderConfigurer
为BeanFactoryPostProcessor
并致电postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
。这会修改BeanFactory
,以便在设置由${my.property:some.default}
创建的bean的属性时允许解析BeanFactory
等属性。SystemPropertyInitializer
实施InitializingBean
并致电afterPropertiesSet()
。在实例化bean并且已设置属性之后,此方法将运行。所以你是对的,SystemPropertyInitializer
在这里没有帮助,因为它在PropertyPlaceholderConfigurer
上设置属性后进行评估。但是,ApplicationContextInitializer
将能够将这些环境属性提升为系统属性,以便XML可以解释它们。
还有一个注意事项,我忘了提及,首先声明的bean之一需要:
<context:property-placeholder/>
虽然看似多余,但它允许您的PropertyPlaceholderConfigurer
bean通过使用您刚推广的环境属性正确评估${ENVIRONMENT:hsql}
。