Spring 3.0 中的多个属性文件

Posted

技术标签:

【中文标题】Spring 3.0 中的多个属性文件【英文标题】:Multiple properties files in Spring 3.0 【发布时间】:2012-02-14 01:04:19 【问题描述】:

我正在开发一个包含多个独立模块的项目,每个模块都有自己的应用程序上下文属性文件。我希望能够加载所有这些属性,以便它们可以被 Spring 用于占位符解析。

以前的问题已经提到了这一点,并且有一篇很好的博客文章 here 描述了如何在每个上下文中使用 PropertyPlaceholderConfigurer,按优先级排序并将 ignoreUnresolveablePlaceholders 设置为 true 以便这些属性文件可以相互交叉引用,而无需炸了。

但是,这并不能解决我的问题,因为我还希望能够将我正在加载的属性用于一些自定义占位符解析(来自我正在解析的一些 yaml 文件)。这需要使用 PropertyPlaceholderHelper,它需要 Properties 对象作为参数。

据我所知,可能的解决方案是:

1) 将所有属性文件合并为一个属性 bean。然后可以使用它来创建 PropertyPlaceholderConfigurer(用于 Spring 的内部占位符解析)并与 PropertyPlaceholderHelper 一起使用(用于我自己的占位符解析)

2) 以某种方式配置 PropertyPlaceholderHelper 以使用 PropertyPlaceholderConfigurers 持有的一组属性及其层次结构,如果我继续遵循该博客文章的建议的话。

不幸的是,我不知道如何做这两个。任何帮助将不胜感激!

PS 看起来 Spring 3.1 将在这里提供很大帮助...不幸的是,我们还没有准备好迁移到它,所以我仍然需要一个解决方案来度过难关!

**** 编辑 ****

感谢到目前为止的回答。它们是很好的答案,但不幸的是对我没有帮助,因为(并且很抱歉之前没有提到这一点)我们目前正在将项目的核心模块与非核心模块分开。这意味着核心模块及其应用程序上下文不能硬编码属性文件的名称。令人沮丧的是,Spring 的类路径扫描似乎被破坏了,因此“classpath*:*.properties”类型的通配符仅在构建单个模块时有效,而不是***项目(我相信这是一个已知问题)。

那么问题是如何将非核心模块中定义的属性文件合并到核心模块中定义的现有属性文件中。目前我正在使用 BeanPostProcessor - 我只是想知道是否有更简单/更优雅的方法来做到这一点?

谢谢

【问题讨论】:

我认为你需要提供至少一个常量目录段,所以classpath*:*.properties 不起作用但classpath*:config/*.properties 会。 【参考方案1】:

这就是您需要做的所有事情:

<context:property-placeholder location="first.properties" order="0" ignore-unresolvable="true"/>
<context:property-placeholder location="second.properties" order="0" ignore-unresolvable="true"/>
<context:property-placeholder location="empty.properties" order="1"/>

问题很简单:如果某个属性占位符对某个属性没有值,它将引发异常,即使存在其他属性占位符。

该解决方案使用order 知道哪个是最后一个property-placeholder,并在所有其他ignore-unresolvable="true" 上设置,这样每个property-placeholder 都有机会提供一个值。在多模块项目中,最后一个 property-placeholder 可以为空或提供故障安全默认值。

注意: 如果您将所有属性占位符设置为 ignore-unresolvable="true",Spring 只会传递您编写的内容而不会引发异常。如果您当然希望它不是String,那么您肯定会在格式转换期间得到java.lang.NumberFormatException: For input string: "$something" 这样的感觉。

注意: 只有第一个(具有最低 order 的)property-placeholder 具有特定属性的值。如果要覆盖属性,请使用比01property-override 更大的order 范围。

使用 Spring 3.2.1 测试,但所有提到的属性都存在于 3.0 中。见JavaDoc of PropertyPlaceholderConfigurer

【讨论】:

【参考方案2】:

以下代码 sn-p 应该可以帮助您入门

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="corePlaceHolder">
    <property name="ignoreUnresolvablePlaceholders" value="true"/>
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
    <property name="searchSystemEnvironment" value="true"/>
    <property name="locations">
        <list>
            <value>classpath*:config/*/config1/*.properties</value>
            <value>classpath*:config/*/config2/*.properties</value>
            <value>classpath*:config/*/config3/*.properties</value>
            <value>classpath*:custom.properties</value>
        </list>
    </property>
</bean>     

您可以将属性文件存储在以下层次结构中,确保可以通过类路径访问配置

config
  config1
     a.properties
  config2
     b.properties
  config3
     c.properties
custom.properties

【讨论】:

【参考方案3】:

您可以很容易地将多个属性文件收集到一个 bean 中:

<bean id="allProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="singleton" value="true"/>
  <property name="ignoreResourceNotFound" value="true"/>
  <property name="locations">
    <list>
      <value>classpath*:default.properties</value>
      <value>classpath*:overrides.properties</value>
      <value>file:$APP_HOME/**/*.properties</value>
    </list>
  </property>
</bean>

这个特定的示例将收集您的 APP_HOME 中类路径和属性文件中的所有 default.properties、overrides.properties。现在您可以从 ProperyPlaceholderConfigurer 或您的自定义后处理器中引用此 bean。

【讨论】:

以上是关于Spring 3.0 中的多个属性文件的主要内容,如果未能解决你的问题,请参考以下文章

Spring配置文件中的parent与abstract

如何解决“在Android独立路径中找到多个文件'project.properties'”Android Studio 3.0 Beta-6中的错误

是否可以从 Maven 多模块项目的父模块中的配置文件夹加载 Spring-Boot 属性?

注解形式读取properties文件中的属性

使用 XSLT 2.0/3.0 使用多个步骤将 CDATA 中的纯文本解析为 html。那里的一部分

Spring 3.0 学习-DI 依赖注入_创建Spring 配置-使用一个或多个XML 文件作为配置文件,使用自动注入(byName),在代码中使用注解代替自动注入,使用自动扫描代替xml中bea(