我有一个带有以下内容的Spring Boot应用程序application.yml
- 基本上从这里开始:
info: build: artifact: ${project.artifactId} name: ${project.name} description: ${project.description} version: ${project.version}
我可以注入特定的值,例如
@Value("${info.build.artifact}") String value
但是,我想注入整个地图,例如:
@Value("${info}") Mapinfo
是(或类似的)可能吗?显然,我可以直接加载yaml,但是想知道Spring是否已经支持了某些东西.
下面的解决方案是@Andy Wilkinson解决方案的简写,除了它不必使用单独的类或带@Bean
注释的方法.
application.yml:
input: name: raja age: 12 somedata: abcd: 1 bcbd: 2 cdbd: 3
SomeComponent.java:
@Component @EnableConfigurationProperties @ConfigurationProperties(prefix = "input") class SomeComponent { @Value("${input.name}") private String name; @Value("${input.age}") private Integer age; private HashMap<String, Integer> somedata; public HashMap<String, Integer> getSomedata() { return somedata; } public void setSomedata(HashMap<String, Integer> somedata) { this.somedata = somedata; } }
我们可以同时兼顾@Value
注释@ConfigurationProperties
,没有任何问题.但是吸气剂和孵化器很重要,@EnableConfigurationProperties
必须要有@ConfigurationProperties
工作.
我从@Szymon Stepniak提供的groovy解决方案中尝试了这个想法,认为它对某人有用.
您可以使用@ConfigurationProperties
以下方式注入地图:
import java.util.HashMap; import java.util.Map; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @EnableAutoConfiguration @EnableConfigurationProperties public class MapBindingSample { public static void main(String[] args) throws Exception { System.out.println(SpringApplication.run(MapBindingSample.class, args) .getBean(Test.class).getInfo()); } @Bean @ConfigurationProperties public Test test() { return new Test(); } public static class Test { private Map<String, Object> info = new HashMap<String, Object>(); public Map<String, Object> getInfo() { return this.info; } } }
在问题中使用yaml运行此操作会产生:
{build={artifact=${project.artifactId}, version=${project.version}, name=${project.name}, description=${project.description}}}
有多种选项可用于设置前缀,控制缺少属性的处理方式等.有关详细信息,请参阅javadoc.
要从配置中检索地图,您将需要配置类。不幸的是,@ Value注释无法解决问题。
Application.yml
entries: map: key1: value1 key2: value2
配置类:
@Component @ConfigurationProperties("entries") @Getter @Setter public static class MyConfig { private Map<String, String> map; }
我今天遇到了同样的问题,但不幸的是Andy的解决方案对我不起作用.在Spring Boot 1.2.1.RELEASE中它更容易,但你必须要注意一些事情.
这是我的有趣部分application.yml
:
oauth: providers: google: api: org.scribe.builder.api.Google2Api key: api_key secret: api_secret callback: http://callback.your.host/oauth/google
providers
map只包含一个map条目,我的目标是为其他OAuth提供程序提供动态配置.我想将此映射注入到一个服务中,该服务将根据此yaml文件中提供的配置初始化服务.我最初的实施是:
@Service @ConfigurationProperties(prefix = 'oauth') class OAuth2ProvidersService implements InitializingBean { private Map<String, Map<String, String>> providers = [:] @Override void afterPropertiesSet() throws Exception { initialize() } private void initialize() { //.... } }
启动应用程序后,providers
映射OAuth2ProvidersService
未初始化.我尝试了Andy建议的解决方案,但它没有用.我在该应用程序中使用Groovy,因此我决定删除private
并让Groovy生成getter和setter.所以我的代码看起来像这样:
@Service @ConfigurationProperties(prefix = 'oauth') class OAuth2ProvidersService implements InitializingBean { Map<String, Map<String, String>> providers = [:] @Override void afterPropertiesSet() throws Exception { initialize() } private void initialize() { //.... } }
在那之后,一切都变得很有效.
虽然有一件事值得一提.在我开始工作之后,我决定创建这个字段,private
并在setter方法中为setter提供直接参数类型.不幸的是它不会那样.它导致org.springframework.beans.NotWritablePropertyException
消息:
Invalid property 'providers[google]' of bean class [com.zinvoice.user.service.OAuth2ProvidersService]: Cannot access indexed value in property referenced in indexed property path 'providers[google]'; nested exception is org.springframework.beans.NotReadablePropertyException: Invalid property 'providers[google]' of bean class [com.zinvoice.user.service.OAuth2ProvidersService]: Bean property 'providers[google]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
如果您在Spring Boot应用程序中使用Groovy,请记住这一点.