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

Ste*_*art 2 java system-properties spring-batch spring-batch-admin property-placeholder

根据这个答案,您可以使用 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>
Run Code Online (Sandbox Code Playgroud)

SystemPropertyInitializer用于afterPropertiesSet()设置系统属性,显然这是在配置PropertyPlaceholderConfigurer发生的。

有可能实现这一目标吗?

Dea*_*ark 5

最简单的解决方案是将环境属性作为命令行参数传递,因此可以将其解析为系统属性。

如果这不是一个选项,您可以实施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());
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,您似乎正在使用 Spring Batch Admin,因此您可以通过在web.xml文件中添加一些内容来注册初始化程序:

<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>org.your.package.EnvironmentPropertyInitializer</param-value>
</context-param>
Run Code Online (Sandbox Code Playgroud)

由于评论而添加背景似乎还不够:这是相关的类以及它们被调用/评估的顺序。

  1. 告诉ApplicationContextInitializerSpring 应用程序如何加载应用程序上下文,并可用于设置 bean 配置文件,以及更改上下文的其他方面。这会在上下文完全创建之前执行。
  2. PropertyPlaceholderConfigureraBeanFactoryPostProcessor并调用postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)。这会修改BeanFactory以便允许解析属性,例如${my.property:some.default}在由 .创建 bean 时设置 bean 的属性BeanFactory
  3. 实现并调用SystemPropertyInitializer。该方法在 bean 实例化并设置属性后运行。InitializingBeanafterPropertiesSet()

所以你是对的,SystemPropertyInitializer在这里不会有帮助,因为它在 . 上设置属性后进行评估PropertyPlaceholderConfigurer。但是ApplicationContextInitializer,将能够将这些环境属性提升为系统属性,以便 XML 可以解释它们。

还有一点我忘了提及,第一个声明的 bean 之一需要是:

 <context:property-placeholder/>
Run Code Online (Sandbox Code Playgroud)

虽然它看起来多余,但它将允许您的bean通过使用您刚刚提升的环境属性PropertyPlaceholderConfigurer来正确评估。${ENVIRONMENT:hsql}