【问题标题】:Loading Properties with Spring (via System Properties)使用 Spring 加载属性(通过系统属性)
【发布时间】:2011-02-16 21:15:14
【问题描述】:

我的问题如下:

我有 server.properties 用于不同的环境。这些属性的路径是通过名为propertyPath 的系统属性提供的。我如何指示我的applicationContext.xml 加载具有给定propertyPath 系统属性的属性,而没有一些丑陋的MethodInvokingBean 调用System.getProperty('');

我的 applicationContext.xml

<bean id="systemPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
        <property name="placeholderPrefix" value="sys{"/>
        <property name="properties">
            <props>
                <prop key="propertyPath">/default/path/to/server.properties</prop>
            </props>
        </property>
    </bean>


    <bean id="propertyResource" class="org.springframework.core.io.FileSystemResource" dependency-check="all" depends-on="systemPropertyConfigurer">
        <constructor-arg value="sys{propertyPath}"/>
    </bean>

    <bean id="serviceProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="location" ref="propertyResource"/>
    </bean>

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" ref="propertyResource"/>
        <property name="placeholderPrefix" value="prop{"/>

        <property name="ignoreUnresolvablePlaceholders" value="true"/>
        <property name="ignoreResourceNotFound" value="false"/>
    </bean>

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
         <property name="jndiName" value="prop{datasource.name}"/>
    </bean>

使用这种配置,propertyResource 总是抱怨

java.io.FileNotFoundException: sys{propertyPath} (The system cannot find the file specified)

有什么建议吗? ;-) 谢谢加布

编辑:

现在我调试了 bean 的加载过程,似乎在创建 systemPropertyConfigurer 之前调用了 propertyConfigurersetLocation 方法,因此 propertyResource 用“sys{propertyPath}”初始化。 我玩过depends-on,但没有运气。

【问题讨论】:

  • 你是怎么玩depends-on的?
  • 'propertyResource depends-on="systemPropertyConfigurer"' 似乎没有效果。 propertyResource 首先被初始化,可能是因为它是用 constructor-arg 初始化的

标签: spring properties


【解决方案1】:

你有两个选择:

  • 使用sys: 作为前缀(因此使用sys:propertyPath

  • 将占位符配置器的placeholderSuffix 属性设置为},以便您可以使用sys{prop} 访问这些属性。如果省略此属性,则必须使用sys{prop

【讨论】:

  • 感谢您的提示。但我无法让它工作。也许我错过了什么。它总是抛出一个 FileNotFoundEx ,其属性名称为文件。默认的 placeholderSuffix 是 } 所以不需要指定它我认为 bean 的加载顺序有问题
【解决方案2】:

好的。我解决了。问题是我的两个 PropertyPlaceholders 都是 BeanFactoryPostProcessor,它们在加载上下文后得到处理,但属性是在之后设置的。所以不可能用另一个来填充一个 PropertyPlaceholder

这是我的代码解决方案 ;-)

package property.util;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Properties;

/**
 * ConfigurablePropertyPlaceholder takes instructions which SystemProperty
 * contains the path to the propertyfile to load.
 *
 * @author Gabe Kaelin
 * 
 */
public class ConfigurablePropertyPlaceholder extends PropertyPlaceholderConfigurer {


    private String propertyLocationSystemProperty;
    private String defaultPropertyFileName;


    public String getPropertyLocationSystemProperty() {
        return propertyLocationSystemProperty;
    }

    public void setPropertyLocationSystemProperty(String propertyLocationSystemProperty) {
        this.propertyLocationSystemProperty = propertyLocationSystemProperty;
    }

    public String getDefaultPropertyFileName() {
        return defaultPropertyFileName;
    }

    public void setDefaultPropertyFileName(String defaultPropertyFileName) {
        this.defaultPropertyFileName = defaultPropertyFileName;
    }

    /**
     * Overridden to fill the location with the path from the {@link #propertyLocationSystemProperty}
     *
     * @param props propeties instance to fill
     * @throws IOException
     */

    @Override
    protected void loadProperties(Properties props) throws IOException {
        Resource location = null;
        if(StringUtils.isNotEmpty(propertyLocationSystemProperty)){

            String propertyFilePath = System.getProperties().getProperty(propertyLocationSystemProperty);
            StringBuilder pathBuilder = new StringBuilder(propertyFilePath);

            if(StringUtils.isNotEmpty(defaultPropertyFileName) && !propertyFilePath.endsWith(defaultPropertyFileName)){
                pathBuilder.append("/").append(defaultPropertyFileName);
            }

            location = new FileSystemResource(pathBuilder.toString());
        }

        setLocation(location);
        super.loadProperties(props);
    }
}

相应的 applicationContext.xml 条目

<bean id="propertyConfigurer" class="property.util.ConfigurablePropertyPlaceholder">
  <property name="propertyLocationSystemProperty" value="propertyPath" />
  <property name="defaultPropertyFileName" value="server.properties" />
  <property name="ignoreResourceNotFound" value="false"/>
</bean>

可以启动java进程

java -DpropertyPath=/path/to/properties

它会加载属性,它们在 applicationContext.xml 中可用

【讨论】:

    【解决方案3】:

    扩展 PropertyPlaceholderConfigurer 的解决方案看起来不错,但它也应该依赖于标准 org.springframework.beans.factory.config.PropertiesFactoryBean 实现而无需编写任何额外代码。

    只需使用将由 Spring 解析的变量引用。

    例如

    如下配置spring:

    <bean id="configProp"
          class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="locations">
            <list>
                <value>file:${propertyPath}</value>
            </list>
        </property>
    </bean>
    

    一旦您使用 env 变量 (propertyPath) 调用 Java,Spring 将解析它,加载属性文件并将其注入到应用程序上下文中

    java -DpropertyPath=/path/to/properties

    【讨论】:

    • 您甚至可以在propertyPath未设置时配置默认值:${propertyPath:defaultValue}
    猜你喜欢
    • 2016-04-24
    • 1970-01-01
    • 1970-01-01
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多