如何在 Spring applicationContext.xml 中读取 JVM 参数
Posted
技术标签:
【中文标题】如何在 Spring applicationContext.xml 中读取 JVM 参数【英文标题】:How do I read JVM arguments in the Spring applicationContext.xml 【发布时间】:2011-08-01 16:15:15 【问题描述】:我有一个带有 Spring 的 JSF Web 应用程序,我正在尝试找出一种从 applicationContext.xml 引用 JVM 参数的方法。我使用环境参数启动 JVM(例如,-Denv=development)。我找到并尝试了几种不同的方法,包括:
<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" />
【问题讨论】:
【参考方案1】:可以使用Spring EL表达式,那么#systemProperties.test
对应-Dtest="hallo welt"
在你的情况下应该是:
<bean id="myBean" class="com.foo.bar.myClass">
<property name="environment">
<value>#systemProperties.environment</value>
</property>
</bean>
#
代替 $
没错!
$
指的是占位符,而#
指的是bean,systemProperties
是一个bean。
可能只是拼写错误,但可能是您的问题的原因:在命令行语句的示例中,您将变量命名为 env
(例如
-Denv=development
...
但在 spring 配置中,您将其命名为 environment
。但当然两者必须相等!
【讨论】:
我使用这种方法得到的结果与我在示例中使用的方法相同。字符串 "#systemProperties.environment" 是传递给 setter 方法的内容。 @jinxed:我想我找到了最后一个问题,有一个拼写错误。 - 查看我的扩展答案。【参考方案2】:如果您注册 PropertyPlaceholderConfigurer,它将使用系统属性作为后备。
例如,添加
<context:property-placeholder/>
到您的配置。然后,您可以在 XML 配置或 @Value
注释中使用 $environment
。
【讨论】:
当我将它添加到配置中时,我从数据库加载的属性会被这个属性占位符覆盖。修改了原始描述。 如何加载数据库属性?它们是 PropertyPlaceholderConfigurer 配置的一部分吗? 它们是通过 JDBC 使用问题(上)中显示的配置加载的... 抱歉,我看不到它们是如何加载的? 好的,当您说属性被属性占位符覆盖时,您是指 $environment 属性占位符吗?还是所有属性?您如何引用从数据库加载的属性?【参考方案3】:您可以像这样根据系统属性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 参数? 这就是我在你的问题中看到的:I am starting the JVM with an environment argument (-Denv=development, for example)
我还在你编辑的问题中提到你提到你正在从数据库中读取一些属性。是否有任何限制只能从 1 个来源读取属性?
所有属性都是从数据库中加载的。我理解使用 PropertyPlaceholderConfigurer 拉入 JVM 参数的概念,但是当我使用 PropertyPlaceholderConfigurer 时,已成功加载的数据库属性现在丢失了。【参考方案4】:
使用#systemProperties['env']
。基本上将Java命令行中使用的propertyName作为-DpropertyName=value
传递。在这种情况下是-Denv=development
,所以使用env
。
【讨论】:
【参考方案5】:有趣的是,Spring 已经发展到使用 PropertySources 更优雅地处理这种需求: http://spring.io/blog/2011/02/15/spring-3-1-m1-unified-property-management/
如果您正在开发 Web 应用程序,通过一些配置和自定义 ApplicationInitializer,您可以让属性占位符处理 System、Environment 和自定义属性。 Spring 提供了在 Spring 配置中使用的 PropertySourcesPlaceholderConfigurer。那将在您的属性文件中查找属性,然后是系统,最后是环境。
【讨论】:
【参考方案6】:春季 3.0.7
<context:property-placeholder location="classpath:$env:config-prd.properties" />
在运行时设置: -Denv=config-dev.properties
如果没有设置“env”将使用默认的“config-prd.properties”。
【讨论】:
以上是关于如何在 Spring applicationContext.xml 中读取 JVM 参数的主要内容,如果未能解决你的问题,请参考以下文章
spring_03ApplicationContext三种经常用到的实现