使用Spring以编程方式访问属性文件?

Mar*_*eon 131 spring properties

我们使用下面的代码为Spring bean注入属性文件中的属性.

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations" value="classpath:/my.properties"/>
</bean>

<bean id="blah" class="abc">
    <property name="path" value="${the.path}"/>
</bean>
Run Code Online (Sandbox Code Playgroud)

有没有办法以编程方式访问属性?我正在尝试做一些没有依赖注入的代码.所以我想要一些像这样的代码:

PropertyPlaceholderConfigurer props = new PropertyPlaceholderConfigurer();
props.load("classpath:/my.properties");
props.get("path");
Run Code Online (Sandbox Code Playgroud)

ska*_*man 164

PropertiesLoaderUtils怎么样?

Resource resource = new ClassPathResource("/my.properties");
Properties props = PropertiesLoaderUtils.loadProperties(resource);
Run Code Online (Sandbox Code Playgroud)

  • 这是一个问题,这与我的有什么不同,还有两张票并且第二张贴... (5认同)
  • 我试图尽可能地接近他所拥有的东西,因为没有提供足够的细节,我被多次投票.无论如何,你的答案值得投票,因为它是正确的,我想我只是嫉妒我也没有获得2票,大声笑. (5认同)
  • 打败我,我没有投票:)我不会使用'PropertyPlaceholderConfigurer`,虽然这对任务来说太过分了. (3认同)
  • 如果文件放置在外部目录(假设是 config 文件夹)中,我们应该在路径中给出什么? (2认同)

ant*_*tix 50

如果您只想从代码访问占位符值,则有@Value注释:

@Value("${settings.some.property}")
String someValue;
Run Code Online (Sandbox Code Playgroud)

访问占位符从SPEL使用以下语法:

#('${settings.some.property}')
Run Code Online (Sandbox Code Playgroud)

要将配置公开给已关闭SPEL的视图,可以使用此技巧:

package com.my.app;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class PropertyPlaceholderExposer implements Map<String, String>, BeanFactoryAware {  
    ConfigurableBeanFactory beanFactory; 

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = (ConfigurableBeanFactory) beanFactory;
    }

    protected String resolveProperty(String name) {
        String rv = beanFactory.resolveEmbeddedValue("${" + name + "}");

        return rv;
    }

    @Override
    public String get(Object key) {
        return resolveProperty(key.toString());
    }

    @Override
    public boolean containsKey(Object key) {
        try {
            resolveProperty(key.toString());
            return true;
        }
        catch(Exception e) {
            return false;
        }
    }

    @Override public boolean isEmpty() { return false; }
    @Override public Set<String> keySet() { throw new UnsupportedOperationException(); }
    @Override public Set<java.util.Map.Entry<String, String>> entrySet() { throw new UnsupportedOperationException(); }
    @Override public Collection<String> values() { throw new UnsupportedOperationException(); }
    @Override public int size() { throw new UnsupportedOperationException(); }
    @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException(); }
    @Override public void clear() { throw new UnsupportedOperationException(); }
    @Override public String put(String key, String value) { throw new UnsupportedOperationException(); }
    @Override public String remove(Object key) { throw new UnsupportedOperationException(); }
    @Override public void putAll(Map<? extends String, ? extends String> t) { throw new UnsupportedOperationException(); }
}
Run Code Online (Sandbox Code Playgroud)

然后使用曝光器将属性公开给视图:

<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" id="tilesViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
    <property name="attributesMap">
        <map>
            <entry key="config">
                <bean class="com.my.app.PropertyPlaceholderExposer" />
            </entry>
        </map>
    </property>
</bean>
Run Code Online (Sandbox Code Playgroud)

然后在视图中,使用这样的公开属性:

${config['settings.some.property']}
Run Code Online (Sandbox Code Playgroud)

此解决方案的优势在于您可以依赖context:property-placeholder标记注入的标准占位符实现.

现在作为最后一点,如果您确实需要捕获所有占位符属性及其值,则必须通过StringValueResolver管道它们以确保占位符在预期的属性值内工作.以下代码将执行此操作.

package com.my.app;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.util.StringValueResolver;

public class AppConfig extends PropertyPlaceholderConfigurer implements Map<String, String> {

    Map<String, String> props = new HashMap<String, String>();

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
            throws BeansException {

        this.props.clear();
        for (Entry<Object, Object> e: props.entrySet())
            this.props.put(e.getKey().toString(), e.getValue().toString());

        super.processProperties(beanFactory, props);
    }

    @Override
    protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
            StringValueResolver valueResolver) {

        super.doProcessProperties(beanFactoryToProcess, valueResolver);

        for(Entry<String, String> e: props.entrySet())
            e.setValue(valueResolver.resolveStringValue(e.getValue()));
    }

    // Implement map interface to access stored properties
    @Override public Set<String> keySet() { return props.keySet(); }
    @Override public Set<java.util.Map.Entry<String, String>> entrySet() { return props.entrySet(); }
    @Override public Collection<String> values() { return props.values(); }
    @Override public int size() { return props.size(); }
    @Override public boolean isEmpty() { return props.isEmpty(); }
    @Override public boolean containsValue(Object value) { return props.containsValue(value); }
    @Override public boolean containsKey(Object key) { return props.containsKey(key); }
    @Override public String get(Object key) { return props.get(key); }
    @Override public void clear() { throw new UnsupportedOperationException(); }
    @Override public String put(String key, String value) { throw new UnsupportedOperationException(); }
    @Override public String remove(Object key) { throw new UnsupportedOperationException(); }
    @Override public void putAll(Map<? extends String, ? extends String> t) { throw new UnsupportedOperationException(); }
}
Run Code Online (Sandbox Code Playgroud)

  • @WardC你不能注入最后的领域.但是,您可以注入构造函数参数并在构造函数中设置最终字段值.请参阅http://stackoverflow.com/questions/2306078/spring-constructor-injection-of-primitive-values-properties-with-annotation-b/2306468#2306468和http://stackoverflow.com/questions/4203302/how -to-注入-a值到豆构造-使用的注解 (2认同)

Ash*_*oyi 49

信用:在Spring中以编程方式访问属性而无需重新读取属性文件

我发现了一个很好的实现,在spring中以编程方式访问属性,而无需重新加载spring已经加载的相同属性.[另外,不需要在源代码中硬编码属性文件位置]

通过这些更改,代码看起来更清晰,更易于维护.

这个概念非常简单.只需扩展spring默认属性占位符(PropertyPlaceholderConfigurer)并捕获它在局部变量中加载的属性

public class SpringPropertiesUtil extends PropertyPlaceholderConfigurer {

    private static Map<String, String> propertiesMap;
    // Default as in PropertyPlaceholderConfigurer
    private int springSystemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;

    @Override
    public void setSystemPropertiesMode(int systemPropertiesMode) {
        super.setSystemPropertiesMode(systemPropertiesMode);
        springSystemPropertiesMode = systemPropertiesMode;
    }

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException {
        super.processProperties(beanFactory, props);

        propertiesMap = new HashMap<String, String>();
        for (Object key : props.keySet()) {
            String keyStr = key.toString();
            String valueStr = resolvePlaceholder(keyStr, props, springSystemPropertiesMode);
            propertiesMap.put(keyStr, valueStr);
        }
    }

    public static String getProperty(String name) {
        return propertiesMap.get(name).toString();
    }

}
Run Code Online (Sandbox Code Playgroud)

用法示例

SpringPropertiesUtil.getProperty("myProperty")
Run Code Online (Sandbox Code Playgroud)

Spring配置发生了变化

<bean id="placeholderConfigMM" class="SpringPropertiesUtil">
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
    <property name="locations">
    <list>
        <value>classpath:myproperties.properties</value>
    </list>
    </property>
</bean>
Run Code Online (Sandbox Code Playgroud)

希望这有助于解决您遇到的问题

  • 这不是完整的实现,也无法正常工作.PropertyPlaceholderConfigurer使用PropertyPlaceholderHelper替换所有占位符属性,包括嵌套占位符.在Kalinga的实现中,如果您有类似myFile = $ {myFolder} /myFile.txt的内容,那么您使用密钥"myFile"从地图获取的文字属性值将为$ {myFolder} /myFile.txt. (7认同)
  • 我尝试将此解决方法应用于 Spring 3.1+ 的“新”PropertySourcesPlaceholderConfigurer,但我发现方法 processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) 现在已被弃用,因此现在无法访问“道具”参数。查看 PropertySourcesPlaceholderConfigurer 的来源找不到公开属性的干净方法。有什么想法可以做到吗?谢谢! (2认同)

Zoi*_*erg 44

我做到了这一点并且有效.

Properties props = PropertiesLoaderUtils.loadAllProperties("my.properties");
PropertyPlaceholderConfigurer props2 = new PropertyPlaceholderConfigurer();
props2.setProperties(props);
Run Code Online (Sandbox Code Playgroud)

这应该工作.


enk*_*kor 25

您还可以使用spring utils,或通过PropertiesFactoryBean加载属性.

<util:properties id="myProps" location="classpath:com/foo/myprops.properties"/>
Run Code Online (Sandbox Code Playgroud)

要么:

<bean id="myProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="location" value="classpath:com/foo/myprops.properties"/>
</bean>
Run Code Online (Sandbox Code Playgroud)

然后你可以在你的应用程序中选择它们:

@Resource(name = "myProps")
private Properties myProps;
Run Code Online (Sandbox Code Playgroud)

并在配置中另外使用这些属性:

<context:property-placeholder properties-ref="myProps"/>
Run Code Online (Sandbox Code Playgroud)

这也在文档中:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#xsd-config-body-schemas-util-properties


小智 10

创建一个如下所示的类

    package com.tmghealth.common.util;

    import java.util.Properties;

    import org.springframework.beans.BeansException;

    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

    import org.springframework.context.annotation.Configuration;

    import org.springframework.context.annotation.PropertySource;

    import org.springframework.stereotype.Component;


    @Component
    @Configuration
    @PropertySource(value = { "classpath:/spring/server-urls.properties" })
    public class PropertiesReader extends PropertyPlaceholderConfigurer {

        @Override
        protected void processProperties(
                ConfigurableListableBeanFactory beanFactory, Properties props)
                throws BeansException {
            super.processProperties(beanFactory, props);

        }

    }
Run Code Online (Sandbox Code Playgroud)

然后,无论您想要访问哪个属性使用

    @Autowired
        private Environment environment;
    and getters and setters then access using 

    environment.getProperty(envName
                    + ".letter.fdi.letterdetails.restServiceUrl");
Run Code Online (Sandbox Code Playgroud)

- 在访问器类中编写getter和setter

    public Environment getEnvironment() {
            return environment;
        }`enter code here`

        public void setEnvironment(Environment environment) {
            this.environment = environment;
        }
Run Code Online (Sandbox Code Playgroud)


Aug*_*tto 6

您可以通过Environment类获取您的属性。作为文档:

属性在几乎所有应用程序中都扮演着重要的角色,并且可能来自各种来源:属性文件、JVM 系统属性、系统环境变量、JNDI、servlet 上下文参数、ad-hoc 属性对象、映射等。与属性相关的环境对象的作用是为用户提供方便的服务接口,用于配置属性源并从中解析属性。

将 Environment 作为env变量,只需调用:

env.resolvePlaceholders("${your-property:default-value}")
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式获取“原始”属性:

env.getProperty("your-property")
Run Code Online (Sandbox Code Playgroud)

它将搜索 spring 已注册的所有属性源。

您可以通过以下方式获得环境:

  • 通过实现ApplicationContextAware然后调用getEnvironment()上下文来注入 ApplicationContext
  • 实施EnvironmentAware

它是通过类的实现获得的,因为属性是在应用程序启动的早期阶段解析的,因为它们可能是 bean 构造所必需的。

阅读有关文档的更多信息:spring Environment 文档