我该如何在Spring的applicationContext.xml中读取JVM参数?

21

我有一个使用Spring的JSF Web应用程序,我正在尝试找出一种从applicationContext.xml引用JVM参数的方法。我通过一个环境参数(例如-Denv = development)启动JVM。我找到并尝试了几种不同的方法,包括:

<bean id="myBean" class="com.foo.bar.myClass">
  <property name="environment">
    <value>${environment}</value>
  </property>
</bean>

然而,在MyClass中调用setter方法时,传递的是字符串"${environment}",而不是"development"。我已经采取了一个解决方法,使用System.getProperty()来实现,但如果能够通过Spring来设置这些值会更好、更简洁。有什么办法可以做到这一点吗?

编辑: 在此之前,我应该提到的是,我正在使用JDBC连接从数据库加载属性。这似乎增加了复杂性,因为当我在配置文件中添加属性占位符时,从数据库加载的属性会被属性占位符覆盖。我不确定这是否与顺序有关。就像我可以做其中之一,但不能同时做两件事。

编辑: 我目前正在使用以下配置加载属性:

<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="jdbc.mydb.myschema"/> 
</bean>

<bean id="props" class="com.foo.bar.JdbcPropertiesFactoryBean">
    <property name="jdbcTemplate">
        <bean class="org.springframework.jdbc.core.JdbcTemplate">
            <constructor-arg ref="myDataSource" />
        </bean>
    </property>
</bean>

<context:property-placeholder properties-ref="props" />
6个回答

27

你可以使用Spring EL表达式,这样就是#{systemProperties.test},对应于-Dtest="hallo welt"

在你的情况下,应该是:

<bean id="myBean" class="com.foo.bar.myClass">
  <property name="environment">
    <value>#{systemProperties.environment}</value>
  </property>
</bean>

# 而不是 $,这并不是错误!

$ 会引用占位符,而 # 引用的是 beans,而且 systemProperties 就是一个 bean。


也许这只是一个拼写错误,但它可能是你问题的原因:在你的命令行语句示例中,你将变量命名为 env

(例如:-Denv=development...

但在 Spring 配置中,你将其命名为 environment。当然,两者必须相等!


我使用这种方法得到的结果与我在示例中使用的方法相同。字符串 "#{systemProperties.environment}" 是传递给setter方法的内容。 - jinxed
@jinxed:我想我找到了最后一个问题,那是一个拼写错误。- 请看我的详细回答。 - Ralph

10
如果您注册了一个PropertyPlaceholderConfigurer,它将使用系统属性作为回退选项。
例如,添加:
<context:property-placeholder/>

将其添加到您的配置中。然后,您可以在XML配置或@Value注释中使用${environment}


它们通过使用上面问题中显示的配置,通过JDBC进行加载... - jinxed
我建议将“props”连接到另一个bean中,以验证com.foo.bar.JdbcPropertiesFactoryBean是否正确加载属性。 - sourcedelica
从数据库中加载属性的占位符正常工作。JVM参数的占位符不起作用,它们无法解析。相反,它们被传递为字符串到bean的访问器。例如,如果我在配置中有value="${environment}",则字符串${environment}将传递给bean,而不是"development" - jinxed
如果您没有将“-Denvironment=development”传递给JVM,而是将该值放入数据库中,会发生什么? - sourcedelica
这应该被接受为正确的答案 - 它允许您在配置文件中定义xxx属性(xxx=val1),并通过命令行-Dxxx=val2添加覆盖此值的可能性。然后,您的代码只包含一个${xxx}引用。为使其正常工作,您必须定义2个带有适当order属性的<context:property-placeholder ..> - Petr Újezdský
显示剩余8条评论

4
您可以根据系统属性env加载属性文件,如下所示:
   <bean id="applicationProperties"
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="ignoreResourceNotFound" value="false" />
      <property name="ignoreUnresolvablePlaceholders" value="true" />
      <property name="searchSystemEnvironment" value="false" />
      <property name="locations">
         <list>
            <value>classpath:myapp-${env:prod}.properties</value>
         </list>
      </property>
   </bean>

如果没有设置env,则将其默认设置为生产环境;否则,开发和测试团队可以通过相应地设置-Denv=development-Denv=testing来拥有他们自己的应用程序版本。

请再次阅读线程。属性正在从数据库中加载。问题是,我如何在配置的其他地方使用JVM参数? - jinxed
这是我在你的问题中看到的内容:我正在使用环境参数 (-Denv=development,例如) 启动 JVM。我还注意到在你编辑后的问题中提到你也从数据库读取了一些属性。有什么限制只能从一个源读取属性吗? - anubhava
所有属性都从数据库中加载。我理解使用PropertyPlaceholderConfigurer来拉取JVM参数的概念,但是当我使用PropertyPlaceholderConfigurer时,已经成功加载的DB属性现在却失踪了。 - jinxed

1
使用#{systemProperties['env']}。基本上将Java命令行中使用的propertyName作为-DpropertyName=value传递。在这种情况下,它是-Denv=development,所以使用env

0
有趣的是,Spring已经演变得更加优雅地处理这个需求,使用PropertySources: http://spring.io/blog/2011/02/15/spring-3-1-m1-unified-property-management/ 只需进行一些配置,如果你正在开发Web应用程序,可能还需要一个自定义的ApplicationInitializer,就可以让属性占位符处理系统、环境和自定义属性。Spring提供了PropertySourcesPlaceholderConfigurer,当你在Spring配置中使用时会用到它。它会先查找属性文件中的属性,然后是系统属性,最后是环境属性。

0

Spring 3.0.7

<context:property-placeholder location="classpath:${env:config-prd.properties}" />

在运行时设置: -Denv=config-dev.properties
如果未设置“env”,则将使用默认值“config-prd.properties”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接