如何使用 Spring 框架从属性文件中获取值到 Map 中?
Posted
技术标签:
【中文标题】如何使用 Spring 框架从属性文件中获取值到 Map 中?【英文标题】:How to get values from property-file into Map using Spring framework? 【发布时间】:2011-04-06 05:34:44 【问题描述】:现在我可以从属性文件中注入值:
@Value("$aaa.prop")
public String someProp;
但我想要更多……
例如我有一些属性文件:
aaa.props=p1,p2,p3
aaa.props.p1=qwe
aaa.props.p2=asd
aaa.props.p3=zxc
我确定它包含属性aaa.props
,而对其他属性一无所知。我想使用这样的代码来映射这些属性:
@Value ("$aaa.props")
public Map<String, String> someProps;
生成的一些道具:p1=qwe,p2=asd,p3=zxc
【问题讨论】:
您可能会发现这个问题的答案很有用:***.com/questions/9259819/…。注入属性对象作为资源,解析列表一并相应地构建您的地图。 【参考方案1】:好吧,我为您构建了一个通用方法:一个工厂 bean,它通过过滤另一个映射来创建一个映射(属性毕竟是一种映射)。
这是工厂 bean:
public class FilteredMapFactoryBean<V> extends
AbstractFactoryBean<Map<String, V>>
private Map<String, V> input;
/**
* Set the input map.
*/
public void setInput(final Map<String, V> input)
this.input = input;
/**
* Set the string by which key prefixes will be filtered.
*/
public void setKeyFilterPrefix(final String keyFilterPrefix)
this.entryFilter = new EntryFilter<String, V>()
@Override
public boolean accept(final Entry<String, V> entry)
return entry.getKey().startsWith(keyFilterPrefix);
;
public static interface EntryFilter<EK, EV>
boolean accept(Map.Entry<EK, EV> entry);
/**
* If a prefix is not enough, you can supply a custom filter.
*/
public void setEntryFilter(final EntryFilter<String, V> entryFilter)
this.entryFilter = entryFilter;
private EntryFilter<String, V> entryFilter;
/**
* @inheritDoc
*/
@Override
public Class<?> getObjectType()
return Map.class;
/**
* @inheritDoc
*/
@Override
protected Map<String, V> createInstance() throws Exception
final Map<String, V> map = new LinkedHashMap<String, V>();
for(final Entry<String, V> entry : this.input.entrySet())
if(this.entryFilter == null || this.entryFilter.accept(entry))
map.put(entry.getKey(), entry.getValue());
return map;
这是一个带有一些示例用法的 spring bean 定义文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- use System.getProperties() as input -->
<bean class="spring.test.FilteredMapFactoryBean" id="javaMap">
<property name="keyFilterPrefix" value="java." />
<property name="input" value="#T(java.lang.System).getProperties()" />
</bean>
<!-- use custom properties as input -->
<bean class="spring.test.FilteredMapFactoryBean" id="customMap">
<property name="keyFilterPrefix" value="hello" />
<property name="input">
<props>
<prop key="hello">Is it me you're looking for?</prop>
<prop key="hello.again">Just called to say: hello.</prop>
<prop key="hello.goodby">You say goodbye and I say hello</prop>
<prop key="goodbye.blue.sky">Did-did-did-did-you hear the falling bombs?</prop>
<prop key="goodbye.ruby.tuesday">Who could hang a name on you?</prop>
</props>
</property>
</bean>
</beans>
这是一个测试类:
public class Tester
@SuppressWarnings("unchecked")
public static void main(final String[] args)
final ApplicationContext context =
new ClassPathXmlApplicationContext("classpath:spring/test/mapFactorybean.xml");
final Map<String, String> javaMap =
(Map<String, String>) context.getBean("javaMap");
print("java.", javaMap);
final Map<String, String> customMap =
(Map<String, String>) context.getBean("customMap");
print("hello.", customMap);
private static void print(final String prefix, final Map<String, String> map)
System.out.println("Map of items starting with " + prefix);
for(final Entry<String, String> entry : map.entrySet())
System.out.println("\t" + entry.getKey() + ":" + entry.getValue());
System.out.println("");
输出如预期:
Map of items starting with java.
java.runtime.name:Java(TM) SE Runtime Environment
java.vm.version:14.2-b01
java.vm.vendor:Sun Microsystems Inc.
java.vendor.url:http://java.sun.com/
java.vm.name:Java HotSpot(TM) Client VM
java.vm.specification.name:Java Virtual Machine Specification
java.runtime.version:1.6.0_16-b01
java.awt.graphicsenv:sun.awt.Win32GraphicsEnvironment
[... etc]
Map of items starting with hello.
hello.goodby:You say goodbye and I say hello
hello:Is it me you're looking for?
hello.again:Just called to say: hello.
【讨论】:
AbstractFactoryBean
默认为单例。在一个上下文中多次使用这个bean(具有不同的属性)会不会有问题?
@naXa 这个答案是 4 岁。这些天 FactoryBeans 有点被弃用了。我会改用 \@Configuration 类【参考方案2】:
恐怕你不能,直接。但是你可以
实现ApplicationContextAware
并将ApplicationContext
设置为您的bean 中的一个字段。
在@PostConstruct
方法调用中context.getBean("$aaa.props")
手动解析结果并将其设置为所需字段
【讨论】:
有没有办法让所有属性找到我需要的?【参考方案3】:你可以使用@Value
。
属性文件:
aaa.props=p1:'qwe',p2:'asd',p3:'zxc'
Java 代码:
@Value("#$aaa.props")
private Map<String,String> someProps;
【讨论】:
这是应该被赞成和接受的答案。此外,那些使用基于 Spring XML 的配置的人可以简单地使用诸如p:someProps="#$aaa.props"
之类的属性来注入它。【参考方案4】:
你可以这样做: Maven依赖
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.2</version>
</dependency>
添加导入。
import javax.annotation.Resource;
...
@Resource (name="propertiesMapName")
public Properties someProps;
在您的 spring xml 应用程序上下文中:
<util:properties id="propertiesMapName" location="classpath:yourFile.properties"/>
你将需要这个命名空间
xmlns:util="http://www.springframework.org/schema/util"
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd
【讨论】:
我能知道为什么我的解决方案中有-1吗?这很有效,我认为这是一种非常干净的方式,我想了解什么是错的。谢谢【参考方案5】:https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config上定义的解决方案
@ConfigurationProperties(prefix="my")
public class Config
private List<String> servers = new ArrayList<String>();
public List<String> getServers()
return this.servers;
【讨论】:
以上是关于如何使用 Spring 框架从属性文件中获取值到 Map 中?的主要内容,如果未能解决你的问题,请参考以下文章