使用Spring加载属性(通过系统属性)

时间:2010-05-07 14:59:06

标签: spring properties

我的问题如下:

我有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)

有什么建议吗? ;-) 谢谢gabe

编辑:

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

3 个答案:

答案 0 :(得分:6)

确定。我解决了问题是我的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

中可用

答案 1 :(得分:2)

扩展PropertyPlaceholderConfigurer的解决方案似乎没问题,但它也应该依赖于标准的org.springframework.beans.factory.config.PropertiesFactoryBean实现,而无需编写任何其他代码。

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

e.g。

按如下方式配置弹簧:

<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

答案 2 :(得分:1)

您有两种选择:

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

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