spring 以编程方式访问由 property-placeholder 创建的属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11415711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:14:48  来源:igfitidea点击:

Programmatic access to properties created by property-placeholder

springproperties

提问by fedor.belov

I'm reading properties file using context:property-placeholder. How can I access them programatically(@Valuedoesn't work - I don't know property titles at the moment of developing)?

我正在使用context:property-placeholder. 我如何以编程方式访问它们(@Value不起作用 - 我在开发时不知道财产所有权)?

The main problem is I can't change applicationContext.xmlfile because it's setted up by "parent" framework

主要问题是我无法更改applicationContext.xml文件,因为它是由“父”框架设置的

ps. It's strange but Environment.getPropertyreturns null

附:这很奇怪,但Environment.getProperty返回null

采纳答案by Sean Patrick Floyd

No you can't. PropertyPlaceholderConfigureris a BeanFactoryPostProcessor, it is only "alive" during bean creation. When it encounters a ${property}notation, it tries to resolve that against its internal properties, but it does not make these properties available to the container.

不,你不能。PropertyPlaceholderConfigurer是 a BeanFactoryPostProcessor,它只是在 bean 创建期间“活着”。当它遇到一个${property}表示法时,它会尝试根据其内部属性解决该问题,但它不会使这些属性对容器可用。

That said: similar questions have appeared again and again, the proposed solution is usually to subclass PropertyPlaceHolderConfigurerand make the Properties available to the context manually. Or use a PropertiesFactoryBean

也就是说:类似的问题一再出现,建议的解决方案通常是手动创建子类PropertyPlaceHolderConfigurer并使属性可用于上下文。或者使用一个PropertiesFactoryBean

回答by mattyboy

We use the following approach to access properties for our applications

我们使用以下方法来访问我们应用程序的属性

<util:properties id="appProperties" location="classpath:app-config.properties" />
<context:property-placeholder properties-ref="appProperties"/>

Then you have the luxury of just autowiring properties into beans using a qualifier.

然后,您可以使用限定符将属性自动装配到 bean 中。

@Component
public class PropertyAccessBean {

    private Properties properties;

    @Autowired
    @Qualifier("appProperties")
    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public void doSomething() {
        String property = properties.getProperty("code.version");
    }

}

If you have more complex properties you can still use ignore-resource-not-found and ignore-unresolvable. We use this approach to externalise some of our application settings.

如果您有更复杂的属性,您仍然可以使用 ignore-resource-not-found 和 ignore-unresolvable。我们使用这种方法来外部化我们的一些应用程序设置。

 <util:properties id="appProperties" ignore-resource-not-found="true"
    location="classpath:build.properties,classpath:application.properties,
                            file:/data/override.properties"/>
 <context:property-placeholder ignore-unresolvable="true" properties-ref="appProperties"/>

回答by vahapt

@Value

annotation works on new releases of Spring (tested on v3.2.2) Here is how it is done:

注释适用于 Spring 的新版本(在 v3.2.2 上测试)这是如何完成的:

  1. Map your properties file in spring configuration file

    <!--Import Info:
    xmlns:context="http://www.springframework.org/schema/context"
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.2.xsd-->
    
    <context:property-placeholder location="classpath:/app-config.properties" />
    
  2. Create app-config.properties inside (root) your source folder

    my.property=test
    my.property2=test2
    
  3. Create a controller class

    @Controller
    public class XRDSBuilder
    {
        @Value("${my.property}")
        private String myProperty;
    
        public String getMyProperty() { return myProperty; }
    }
    
  1. 在 spring 配置文件中映射您的属性文件

    <!--Import Info:
    xmlns:context="http://www.springframework.org/schema/context"
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.2.xsd-->
    
    <context:property-placeholder location="classpath:/app-config.properties" />
    
  2. 在(根)源文件夹中创建 app-config.properties

    my.property=test
    my.property2=test2
    
  3. 创建控制器类

    @Controller
    public class XRDSBuilder
    {
        @Value("${my.property}")
        private String myProperty;
    
        public String getMyProperty() { return myProperty; }
    }
    

Spring will automatically map the content of my.property to your variable inside the controller

Spring 会自动将 my.property 的内容映射到控制器内的变量

Mapping to a list

映射到列表

Property value:

适当的价值:

my.list.property=test,test2,test3

Controller class configuration:

控制器类配置:

@Value("#{'${my.list.property}'.split(',')}")
private List<String> myListProperty;

Advanced mapping

高级映射

@Component("PropertySplitter")
public class PropertySplitter {

    /**
     * Example: one.example.property = KEY1:VALUE1,KEY2:VALUE2
     */
    public Map<String, String> map(String property) {
        return this.map(property, ",");
    }

    /**
     * Example: one.example.property = KEY1:VALUE1.1,VALUE1.2;KEY2:VALUE2.1,VALUE2.2
     */
    public Map<String, List<String>> mapOfList(String property) {
        Map<String, String> map = this.map(property, ";");

        Map<String, List<String>> mapOfList = new HashMap<>();
        for (Entry<String, String> entry : map.entrySet()) {
            mapOfList.put(entry.getKey(), this.list(entry.getValue()));
        }

        return mapOfList;
    }

    /**
     * Example: one.example.property = VALUE1,VALUE2,VALUE3,VALUE4
     */
    public List<String> list(String property) {
        return this.list(property, ",");
    }

    /**
     * Example: one.example.property = VALUE1.1,VALUE1.2;VALUE2.1,VALUE2.2
     */
    public List<List<String>> groupedList(String property) {
        List<String> unGroupedList = this.list(property, ";");

        List<List<String>> groupedList = new ArrayList<>();
        for (String group : unGroupedList) {
            groupedList.add(this.list(group));
        }

        return groupedList;

    }

    private List<String> list(String property, String splitter) {
        return Splitter.on(splitter).omitEmptyStrings().trimResults().splitToList(property);
    }

    private Map<String, String> map(String property, String splitter) {
        return Splitter.on(splitter).omitEmptyStrings().trimResults().withKeyValueSeparator(":").split(property);
    }
}

Property value:

适当的价值:

my.complex.property=test1:value1,test2:value2

Controller class:

控制器类:

@Value("#{PropertySplitter.map('${my.complex.property}')}")
Map<String, String> myComplexProperty;

回答by Maciej Miklas

Spring follows Inversion Of Control approach, this means that we can simply inject particular property into POJO. But there are some cases, when you would like to access property given by name directly from your code - some might see it as anti-pattern - this is palpably true, but lets concentrate on how to do it.

Spring 遵循 Inversion Of Control 方法,这意味着我们可以简单地将特定属性注入 POJO。但是在某些情况下,当您想直接从代码中访问按名称给出的属性时 - 有些人可能会将其视为反模式 - 这显然是正确的,但让我们专注于如何做到这一点。

The PropertiesAccessorbelow provides access to properties loaded by Property Placeholderand encapsulates container specific stuff. It also caches found properties because call on AbstractBeanFactory#resolveEmbeddedValue(String)is not cheap.

PropertiesAccessor下面提供了访问由装载性能Property Placeholder和封装容器具体的东西。它还缓存找到的属性,因为调用AbstractBeanFactory#resolveEmbeddedValue(String)并不便宜。

@Named 
public class PropertiesAccessor {

    private final AbstractBeanFactory beanFactory;

    private final Map<String,String> cache = new ConcurrentHashMap<>(); 

    @Inject 
    protected PropertiesAccessor(AbstractBeanFactory beanFactory) {
        this.beanFactory = beanFactory; 
    } 

    public  String getProperty(String key) { 
        if(cache.containsKey(key)){ 
            return cache.get(key); 
        } 

        String foundProp = null; 
        try { 
            foundProp = beanFactory.resolveEmbeddedValue("${" + key.trim() + "}");        
            cache.put(key,foundProp);        
        } catch (IllegalArgumentException ex) { 
           // ok - property was not found 
        } 

        return foundProp; 
    } 
}

回答by Sandeep

Found answer at below site:

在以下网站找到答案:

http://forum.spring.io/forum/spring-projects/container/106180-programmatic-access-to-properties-defined-for-the-propertyplaceholderconfigurer

http://forum.spring.io/forum/spring-projects/container/106180-programmatic-access-to-properties-defined-for-the-propertyplaceholderconfigurer

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="propertyConfigurer">
<property name="properties" ref="props" />
</bean>
<bean id="props" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="location" value="file:C:/CONFIG/settings.properties"/>
</bean>

回答by TheJeff

Create beans for your properties before putting them in property-placeholder to make the properties easy to access in-code.

在将属性放入属性占位符之前为您的属性创建 bean,以使属性易于在代码中访问。

Ex:

前任:

<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="resources" value="classpath:META-INF/spring/config.properties" />
</bean>

<context:property-placeholder properties-ref="configProperties" ignore-unresolvable="true"/>

Code:

代码:

@Autowired
private PropertiesFactoryBean configProperties;

You can also use @Resource(name="configProperties")

你也可以使用@Resource(name="configProperties")

回答by Sarang

<util:properties id="prop" location="location of prop file" />

This return java.util.Properties object

这返回 java.util.Properties 对象

In JAVA Code

在 JAVA 代码中

Properties prop = (Properties) context.getBean("prop");

Now you can access ,

现在您可以访问,

prop.getProperty("key");

回答by StefanLe

This works if you need to scan multiple locations for your properties ...

如果您需要为您的房产扫描多个位置,这会起作用......

<bean id="yourProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="locations">
        <array value-type="org.springframework.core.io.Resource">
            <value>classpath:yourProperties.properties</value>
            <value>file:../conf/yourProperties.properties</value>
            <value>file:conf/yourProperties.properties</value>
            <value>file:yourProperties.properties</value>
        </array>
    </property>
    <property name="ignoreResourceNotFound" value="true" />
</bean>
<context:property-placeholder properties-ref="yourProperties" ignore-unresolvable="true"/>

And then in your actual classes ...

然后在你的实际课程中......

@Autowired
Properties yourProperties;

Tested using Spring 5.1.4

使用 Spring 5.1.4 测试

回答by Carlos D.

Let's asume that you the properties file defined in that "parent" framework

让我们假设您在该“父”框架中定义的属性文件

<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="location" value="classpath:main.properties" />
</bean>

You can use the @Value annotation in this way:

您可以通过这种方式使用 @Value 注释:

@Value( value = "#{applicationProperties['my.app.property']}" )
private String myProperty;