Spring:加载PropertyPlaceholderConfigurer

时间:2014-06-02 07:51:12

标签: java spring

情况如下:

xml配置如下所示:

<bean id="ppConfig1"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>file:c:\test\env.properties</value>      
            </list>
        </property>
        <property name="ignoreResourceNotFound" value="true" />
    </bean>
    <bean id="string" class="java.lang.String" depends-on="ppConfig1">
        <constructor-arg value="${env.app.type}"/>
    </bean>

     <bean id="ppConfig2"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="string">
        <property name="locations">
            <list>
                <value>file:c:\test\#{string}.properties</value>                
            </list>
        </property>
        <property name="ignoreResourceNotFound" value="false" />
    </bean>

很明显,我想根据env.app.type中的密钥C:\test\env.properties的值加载特定的属性文件(例如app1.properties)。

加载/测试上述配置的代码如下所示:

ApplicationContext context = new ClassPathXmlApplicationContext(
                "SpringBeans.xml"); 
        String ss = (String)context.getBean("string");      
        System.out.println(ss);

这似乎不起作用。它失败并出现以下错误:

  

线程“main”中的异常   org.springframework.beans.factory.BeanInitializationException:可以   不加载属性;嵌套异常是   java.io.FileNotFoundException:C:\ test \ $ {env.app.type} .properties(The   系统找不到指定的文件)   org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:87)

文件c:\test\env.properties如下所示

  

env.app.type = APP1

一个有趣的观察结果是,当我注释掉ppConfig2时,一切正常,并打印出env.app.type的正确值。我愿意接受任何其他建议来解决这个问题。我的基本要求是在运行时根据env.properties中指定的属性选择属性文件。 (我使用的是春季3.1.0)

3 个答案:

答案 0 :(得分:1)

你需要这样的东西:

    <context:component-scan base-package="com.foo.bar" />

    <context:property-placeholder location="file:c:/test/${env.app.type}.properties" />

    <bean id="service" class="com.foo.bar.ExampleService">
        <property name="foo" value="${foo}" />
    </bean>


package com.foo.bar;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource("file:c:/test/env.properties")
public class SpringConfig{

}

&#34; foo&#34;值来自app1.properties文件。基本上,一个文件正在加载@PropertySource,另一个文件正在加载常规属性占位符。

答案 1 :(得分:0)

我认为你正在尝试做一些Spring不喜欢的事情。 bean初始化的正常顺序是:

  • 完全构建bean后处理器
  • 构建其他bean
  • init other beans

只要这3个传递被完全分开,一切都会好的,但你有一个后处理器bean(ppConfig2),这取决于一个简单的bean(string)。

恕我直言,如果可能的话,你应该避免这种结构。即使它现在有效,你也可能会因为你已经处于边缘而在任何修改应用程序环境时出现问题。

使用环境变量或系统属性来避免bean后处理器依赖于另一个bean后处理器是否可以接受?如果是的话,你不会被ppConfig1打扰而只是:

 <bean id="ppConfig2"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="string">
    <property name="locations">
        <list>
            <value>file:c:\test\${configured_env}.properties</value>                
        </list>
    </property>
    <property name="ignoreResourceNotFound" value="false" />
</bean>

如果环境变量或系统属性不是一个选项,您可以使用Andrei Stefan建议的编程配置。

答案 2 :(得分:0)

您可以使用util:properties

执行此操作
<util:properties id="envProperties" location="env.properties"/>
<util:properties id="properties" location="#{envProperties.getProperty('env.app.type')}.properties"/>

<context:property-placeholder properties-ref="envProperties" ignore-unresolvable="true" ignore-resource-not-found="true"/>
<context:property-placeholder properties-ref="properties" ignore-unresolvable="true"/>

顺便说一下,Spring中有一个bug,阻止在location context:property-placeholder {{1}}内的{{1}}属性中评估Spring EL。