Spring 3.1 Environment不适用于用户属性文件

时间:2013-01-05 07:52:15

标签: java spring

我这样做..

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(context);
xmlReader
        .loadBeanDefinitions(new ClassPathResource("SpringConfig.xml"));
PropertySourcesPlaceholderConfigurer propertyHolder = new PropertySourcesPlaceholderConfigurer();
propertyHolder.setLocation(new ClassPathResource(
        "SpringConfig.properties"));
context.addBeanFactoryPostProcessor(propertyHolder);

    ......

context.refresh();

现在在我的@Configuration文件中,如果我这样做,我的SpringConfig.properties中的属性就不会被提取......

@Autowired
private Environment env
.....
env.getProperty("my.property")

但如果我使用

,我就会获得该属性
@Value("${my.property}")
private String myProperty;

我甚至尝试添加这样的几行,但没有用。

ConfigurableEnvironment env = new StandardEnvironment();
propertyHolder.setEnvironment(env);

有人知道为什么我的属性没有加载到Environment中吗?感谢。

4 个答案:

答案 0 :(得分:15)

PropertySourcesPlaceholderConfigurer直接读取属性文件(正如PropertyPlaceholderConfigurer在Spring 3.0中所做的那样),它只是一个后处理器,它不会改变Spring上下文中属性的使用方式 - 在这种情况下,属性仅作为bean定义占位符使用。

使用Environment的PropertySourcesPlaceholderConfigurer反之亦然。

属性源框架在应用程序上下文级别上工作,而属性占位符配置器仅提供在bean定义中处理占位符的功能。要使用属性源抽象,您应该使用@PropertySource注释,即用类似的东西装饰您的配置类 @PropertySource("classpath:SpringConfig.properties")

我相信您可以通过编程方式执行相同的操作,即您可以在刷新上下文之前获取容器的ConfigurableEnvironment,修改其MutablePropertySources(首先需要通过{{获取AbstractApplicationContext environment属性1}})通过context.getEnvironment()但不太可能你想做什么 - 如果你已经有getPropertySources().addFirst(new ResourcePropertySource(new ClassPathResource( "SpringConfig.properties")));注释类,用@Configuration进行装饰要简单得多。

对于@PropertySource("classpath:SpringConfig.properties")实例 - 它将从其应用程序上下文中自动获取属性源(因为它实现了EnvironmentAware),因此您只需要注册它的默认实例。

有关自定义属性源实现的示例,请参阅http://blog.springsource.org/2011/02/15/spring-3-1-m1-unified-property-management/

答案 1 :(得分:3)

本地属性添加到PropertySourcesPlaceholderConfigurersetProperties()setLocation())并不会使其在Environment中可用。

实际上它以相反的方式工作 - Environment充当属性的主要来源(请参阅ConfigurableEnvironment),而PropertySourcesPlaceholderConfigurer可以使用Environment提供属性${...}语法。

答案 2 :(得分:1)

我按照@Boris的建议做了这个..

    PropertySourcesPlaceholderConfigurer propertyHolder = new PropertySourcesPlaceholderConfigurer();
    ConfigurableEnvironment env = new StandardEnvironment();
    env.getPropertySources().addFirst(
            new ResourcePropertySource(new ClassPathResource(
                    "SpringConfig.properties")));
    propertyHolder.setEnvironment(env);
    context.addBeanFactoryPostProcessor(propertyHolder);
            context.register(SpringConfig.class);
            context.refresh();

现在在@Configuration类中,可以使用@Value解析所有属性(包括我自己的属性和系统属性)。

但是将@Autowired转换为@Configuration类的环境中只有系统属性,而不是我在上面设置的SpringConfig.properties。但显然,在上面调用context.refresh()之前,ConfigurableEnvironment也有我的属性。但是一旦调用context.refresh(),我的属性就会从环境中删除,并自动装入@Configuration。

我希望能够使用更好的语法env.getProperty(“my.property”)。有人知道为什么会这样吗?

答案 3 :(得分:0)

我正在加载2种类型的属性,一种是Environment属性,另一种是您通常从中获取的上下文,比如说servletContext.getServletContext()。 我的环境属性定义为:MOD_CONFIG_ROOT,它单独设置在环境中,从而将包含代码的ear文件的位置详细信息分开。这是配置。 [注意:在加载servlet之前我必须首先加载属性文件,以便使用${someProperty}]

来使用属性
<bean id="externalProperties"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>file:#{ systemEnvironment['MOD_CONFIG_ROOT']
                }#{servletContext.contextPath}/users.properties</value>
        </list>
    </property>
    <property name="searchSystemEnvironment" value="true" />
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_FALLBACK" />
</bean>