在设置属性占位符之前,使用SystemPropertyInitializer设置系统属性

时间:2017-03-21 03:31:48

标签: java spring-batch spring-batch-admin system-properties property-placeholder

根据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之后会发生

有可能实现这个目标吗?

1 个答案:

答案 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>

添加背景,因为评论没有看似充足:这里是相关的类及其调用/评估的顺序。

  1. ApplicationContextInitializer告诉Spring Application如何加载应用程序上下文,并可用于设置bean配置文件,以及更改上下文的其他方面。这将在完全创建上下文之前执行
  2. PropertyPlaceholderConfigurerBeanFactoryPostProcessor并致电postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)。这会修改BeanFactory,以便在设置由${my.property:some.default}创建的bean的属性时允许解析BeanFactory等属性。
  3. SystemPropertyInitializer实施InitializingBean并致电afterPropertiesSet()。在实例化bean并且已设置属性之后,此方法将运行。
  4. 所以你是对的,SystemPropertyInitializer在这里没有帮助,因为它在PropertyPlaceholderConfigurer上设置属性后进行评估。但是,ApplicationContextInitializer将能够将这些环境属性提升为系统属性,以便XML可以解释它们。

    还有一个注意事项,我忘了提及,首先声明的bean之一需要:

     <context:property-placeholder/>
    

    虽然看似多余,但它允许您的PropertyPlaceholderConfigurer bean通过使用您刚推广的环境属性正确评估${ENVIRONMENT:hsql}