如何在 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 Boot中常用的三个注解

spring_03ApplicationContext三种经常用到的实现

Springset注入(掌握)

解决spring boot中普通类中使用service为null 的方法

websocket无法注入问题解决方案

如何在 Rails 中重定向到 404?