java 将动态属性映射读入 Spring 管理的 bean

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14760200/
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-10-31 17:18:58  来源:igfitidea点击:

Reading a dynamic property map into Spring managed bean

javaspringdynamicmapjavabeans

提问by kriver

I have a properties file like this:

我有一个这样的属性文件:

my.properties file:
app.One.id=1
app.One.val=60

app.Two.id=5
app.Two.val=75

And I read these values into a map property in my bean in Spring config file like this:

我将这些值读入 Spring 配置文件中 bean 的映射属性中,如下所示:

spring-config.xml:
<bean id="myBean" class="myClass" scope="singleton">
    <property name="myMap">
        <map>
            <entry key="${app.One.id}" value="${app.One.val}"/>
            <entry key="${app.Two.id}" value="${app.Two.val}"/>
        </map>
    </property>
</bean>

This way if I add a new id/val to the properties file, I must add a row in config xml in order to have the new id/val in myMap.

这样,如果我向属性文件添加新的 id/val,我必须在 config xml 中添加一行,以便在 myMap 中拥有新的 id/val。

My question is, is there a way to specify the key-val pairs in spring config file so that the number of key-vals defined in xml can figure out the items in the properties file and create a map. Basically I want to use this xml file in different environments where we use different number of key-value items in properties file. I just don't want to change the xml file in each environment to read in all these values.

我的问题是,有没有办法在 spring 配置文件中指定 key-val 对,以便 xml 中定义的 key-val 数量可以找出属性文件中的项目并创建映射。基本上我想在不同的环境中使用这个 xml 文件,在这些环境中我们在属性文件中使用不同数量的键值项。我只是不想更改每个环境中的 xml 文件以读取所有这些值。

Let me know if you need any other details. Any thoughts/comments is appreciated. Thanks!

如果您需要任何其他详细信息,请告诉我。任何想法/意见表示赞赏。谢谢!

采纳答案by Vitaly

This is done with Spring EL and custom handling.

这是通过 Spring EL 和自定义处理完成的。

It was just interesting for me to try it. It works :)

对我来说尝试它很有趣。有用 :)

application.xml

应用程序.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
    ">

    <util:properties id="values" location="values.properties" />

    <bean id="hello" class="my.Hello">
        <property name="map"
            value="#{T(my.Utils).propsToMap(values, '^(app\.\w*)\.id$', '{idGroup}.val')}" />
    </bean>

</beans>

Utils.java

实用程序

package my;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Utils {

    public static Map<String, String> propsToMap(Properties props,
            String idPatternString, String valuePatternString) {

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

        Pattern idPattern = Pattern.compile(idPatternString);

        for (Enumeration<?> en = props.propertyNames(); en.hasMoreElements();) {
            String key = (String) en.nextElement();
            String mapKey = (String) props.getProperty(key);

            if (mapKey != null) {
                Matcher idMatcher = idPattern.matcher(key);
                if (idMatcher.matches()) {

                    String valueName = valuePatternString.replace("{idGroup}",
                            idMatcher.group(1));
                    String mapValue = props.getProperty(valueName);

                    if (mapValue != null) {
                        map.put(mapKey, mapValue);
                    }
                }
            }
        }

        return map;
    }
}

Hello.java

你好.java

package my;

import java.util.Map;

public class Hello {

    private Map<String, String> map;

    public Map<String, String> getMap() {
        return map;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }
}

values.properties

values.properties

app.One.id=1
app.One.val=60

app.Two.id=5
app.Two.val=75

回答by Haim Raman

Maybe I did not fully understand the issue here...
What about a simplified approach?

也许我没有完全理解这里的问题......
简化方法怎么样?

my.properties file:
1=60
5=75

Application Context

应用上下文

<bean id="myProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="locations">
        <list>
        <value>classpath: my.properties</value>
        </list>
    </property>
</bean> 
<bean id="myClass" class="com.pakage.MyClass">
    <property name="myMap" ref=" myProperties"/>
</bean>

Java Bean

Java Bean

public class MyClass {
    private Map<String , String> myMap;

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    public Map<String , String> getMyMap(){
        return myMap;
    }
}

回答by duffymo

It's a classic environment problem.

这是一个经典的环境问题。

There are two ways to do this:

有两种方法可以做到这一点:

  1. Add an environment string at the end of the appropriate .properties file; pass that value to the app when it starts and let Spring choose the correct one.
  2. Put those dynamic properties in a database and query for them on startup. The JNDI for the database will pick the right values.
  1. 在相应的 .properties 文件末尾添加环境字符串;在应用程序启动时将该值传递给应用程序,并让 Spring 选择正确的值。
  2. 将这些动态属性放在数据库中并在启动时查询它们。数据库的 JNDI 将选择正确的值。

回答by kriver

I did not find an ideal way to solve this issue to have dynamic map property read into spring configuration info. Using DB was also not an option for us. This is what I found to be the best alternative for this:

我没有找到解决这个问题的理想方法来将动态地图属性读入 spring 配置信息。使用 DB 也不是我们的选择。这是我发现的最佳选择:

  • Use a standard format for map key/value pair in the properties file eg: key1 | val1, key2 | val2, key3 | val3, ..., keyn | valn

  • Read this to a String property or List property in configuration bean like here: Use String to List

  • Let injected java class split the items into map in setter.

  • 在属性文件中使用映射键/值对的标准格式,例如:key1 | val1, key2 | val2, key3 | val3, ..., keyn | 瓦恩

  • 将此读取到配置 bean 中的 String 属性或 List 属性,如下所示:Use String to List

  • 让注入的java类在setter中将项目拆分为map。

I'm going to mark this as answer. If anyone else has better ways to do this, comment it out and I will change it to answer.

我要把这个标记为答案。如果其他人有更好的方法来做到这一点,请将其注释掉,我会将其更改为答案。