在SpringBoot中怎么注入各种类型(String,List,Map,Object)配置?
Posted DreamMakers
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在SpringBoot中怎么注入各种类型(String,List,Map,Object)配置?相关的知识,希望对你有一定的参考价值。
在SpringBoot中怎么注入各种类型(String,List,Map,Object)配置?
背景
在开发过程中,绝大多数场景都是要使用一些配置项的。至于配置项如何注入到应用程序中,一直没有过多的关注过。今天抽了点时间实际试了下,这里做个简单的记录,便于需要的朋友了解下。
在下面的讲述中,我们针对下面的一组配置来进行说明,分别演示读取字符串String、列表List、哈希表Map和对象Object进行说明。开发框架为Springboot。
config:
str: 123456
list:
- 1
- 2
- 3
- 4
- 5
map:
1: first
2: second
3: third
entity:
key: name
value: majing
String类型配置注入
对于String类型的配置,注入最简单,只要简单实用@Value注解就可以了,如下:
@Value("$config.str")
private String strConfig;
List类型配置注入
对于List类型的配置,注入有两种方式,如下所示。
(1)如果在application.yaml文件中如下配置,
config:
list:
- 1
- 2
- 3
- 4
- 5
那么直接使用@Value注解就可以了,如下所示:
@Value("$config.list")
private List<Integer> listConfig;
(2)如果在application.yaml文件中不是按照列表格式配置的,
config:
list: 1,2,3,4,5
那么在使用@Value注解时需要注意,使用@Value("$config.list")没法完成解析,这时候需要做如下修改,调用split()方法对读取的字符串值进行分隔,如果分隔符不一样,那直接替换成其他分隔符就好了。
@Value("#'$config.list'.split(',')")
private List<Integer> listConfig;
Map类型配置注入
对于Map类型的注入,在使用@Value注解进行注入的时候一直存在问题,百度了下实现,发现网上贴了几种实现,但是都尝试的写了一遍,发现都没法正常注入。
有篇文章让这么实现,首先配置是这样写:
config:
map: 1: first, 2: second, 3:third
然后在注入的地方这么写:
@Value("#$config.map")
private Map<String,String> mapConfig;
但是实际运行后,会发现根本注入不了,报出如下异常错误:
2020-02-23 09:17:48,156 [main] [org.springframework.boot.SpringApplication] [ERROR] (SpringApplication.java:826)- Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'configController': Unsatisfied dependency expressed through field 'mapConfig'; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'first' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:397)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1429)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
at com.majing.test.springbootdemo.SpringbootdemoApplication.main(SpringbootdemoApplication.java:18)
Caused by: org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'first' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:164)
at org.springframework.beans.factory.support.AbstractBeanFactory.evaluateBeanDefinitionString(AbstractBeanFactory.java:1566)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1231)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:636)
... 19 common frames omitted
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'first' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:217)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:91)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:112)
at org.springframework.expression.spel.ast.InlineMap.getValueInternal(InlineMap.java:130)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:112)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:267)
at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:161)
... 23 common frames omitted
试了网上的几种方式都不行之后,我转变了下思路,不再使用@Value注解进行注入,配置信息格式不变,但是我单独定义一个实体类Config,如下所示:
package com.majing.test.springbootdemo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "config")
public class Config
private String str;
private List<Object> list;
private Map<String,String> map;
public String getStr()
return str;
public void setStr(String str)
this.str = str;
public List<Object> getList()
return list;
public void setList(List<Object> list)
this.list = list;
public Map<String, String> getMap()
return map;
public void setMap(Map<String, String> map)
this.map = map;
在这个配置实体类中,我们定义了String类型、List类型和Map类型字段,然后在Config类上使用@ConfigurationProperties(prefix = “config”)注解来指出该实体类对应的配置项前缀是application.yaml中config开头的配置项,配置项如下:
config:
str: 123456
list:
- 1
- 2
- 3
- 4
- 5
map: 1: first, 2: second, 3: third
或者如下配置:
config:
str: 123456
list:
- 1
- 2
- 3
- 4
- 5
map:
1: first
2: second
3: third
需要说明的是List类型必须按照上述配置,否则没法解析。
通过简单的测试接口,我们可以看到配置已经正确的注入了。
Configstr='123456', list=[1, 2, 3, 4, 5], map=1=first, 2=second, 3=third
Object类型配置注入
在上述Config配置类的基础上,我们假设还有一个实体类对象ConfigEntity,这个实体类里有key和value两个字段(当然实际工作中的会根据自己需要进行自定义)。
配置文件内容如下:
config:
str: 123456
list:
- 1
- 2
- 3
- 4
- 5
map:
1: first
2: second
3: third
entity:
key: name
value: majing
ConfigEntity类的定义如下,使用@ConfigurationProperties(prefix = “config.entity”)进行注入说明:
package com.majing.test.springbootdemo.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "config.entity")
public class ConfigEntity
private String key;
private String value;
public String getKey()
return key;
public void setKey(String key)
this.key = key;
public String getValue()
return value;
public void setValue(String value)
this.value = value;
@Override
public String toString()
return "ConfigEntity" +
"key='" + key + '\\'' +
", value='" + value + '\\'' +
'';
接下来就是Config类的定义了,如下所示,ConfigEntity实例需要经过@Autowired注解进行注入,否则没法将配置项注入。
package com.majing.test.springbootdemo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "config")
public class Config
private String str;
private List<Object> list;
private Map<String,String> map;
@Autowired
private ConfigEntity entity;
public String getStr()
return str;
public void setStr(String str)
this.str = str;
public List<Object> getList()
return list;
public void setList(List<Object> list)
this.list = list;
public Map<String, String> getMap()
return map;
public void setMap(Map<String, String> map)
this.map = map;
@Override
public String toString()
return "Config" +
"str='" + str + '\\'' +
", list=" + list +
", map=" + map +
", entity=" + entity +
'';
在运行程序后,我们可以看到,相关配置都能正确注入,打印出的Config内容为:
Configstr='123456', list=[1, 2, 3, 4, 5], map=1=first, 2=second, 3=third, entity=ConfigEntitykey='name', value='majing'
结语
本文对常见的一些配置注入进行了说明,覆盖了大多数的场景,但是肯定还存在一些其他场景,需要在实际工作中不断的总结。同时,上面的配置是在application.yaml文件中配置的,如果需要引入自定义的属性配置文件,那么还可能需要结合@PropertySource注解一些使用。如果对于Map诸如有更好的方法,可以留言给我,谢谢。
以上是关于在SpringBoot中怎么注入各种类型(String,List,Map,Object)配置?的主要内容,如果未能解决你的问题,请参考以下文章
springboot中如何注入一个多个实现类service接口
springboot @Autowired mapper 爆红解决方案,超详细,罗列各种情况