0

根据this answer,可以使用Spring批处理类org.springframework.batch.support.SystemPropertyInitializer在启动Spring上下文时设置系统属性。使用SystemPropertyInitializer在设置属性占位符前设置系统属性

特别,我希望能够用它来设置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的配置。

有没有可能做到这一点?

回答

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的联系,这样你就可以有轻微除了web.xml文件的初始注册:

<context-param> 
    <param-name>contextInitializerClasses</param-name> 
    <param-value>org.your.package.EnvironmentPropertyInitializer</param-value> 
</context-param> 

添加背景由于评论看起来不够:下面是相关的类和它们被调用/评估的顺序。

  1. ApplicationContextInitializer告诉Spring应用程序如何加载应用程序上下文,可以用来设置豆型材,并改变背景的其他方面。这在之前执行上下文完全创建。
  2. PropertyPlaceholderConfigurerBeanFactoryPostProcessor并且呼叫postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)。这会修改BeanFactory以允许在设置由BeanFactory创建的bean的属性时解析属性,如${my.property:some.default}
  3. SystemPropertyInitializer实施InitializingBean和调用afterPropertiesSet()。这个方法在一个bean被实例化并且属性已经设置之后运行。

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

而更多的一个音符,我忘了提,第一个宣布豆之一将需要:

<context:property-placeholder/> 

虽然它似乎是多余的,它可以让你的PropertyPlaceholderConfigurer bean来使用正确的评价${ENVIRONMENT:hsql}您刚推出的环境属性。

+0

我不确定系统属性和环境属性之间的差异是多么适用。类SystemPropertyInitializer在其代码中调用System.setProperty()。我遇到的是它在* placeholderProperties解析后才会被调用。这个解决方案不会遇到同样的问题吗?我对Spring的生命周期知识还不够自信。 – Stewart

+1

上面增加了详细信息(太长的评论) –