【SpringBoot】@ConfigurationProperties 及 @Value 的区别和用法

SpringBoot @Value 和 @ConfigurationProperties 的区别和用法

背景

SpringBoot 项目中,我们经常在配置文件application.propertiesapplication.yml 中存放配置参数。
本文就对SpringBoot@Value@ConfigurationProperties注解的区别和用法进行介绍

@ConfigurationProperties·和·@Value·的区别

参考: SpringBoot | @Value 和 @ConfigurationProperties 的区别

对比内容@ConfigurationProperties@Value
功能批量注入配置文件中的属性一个个指定
松散绑定(松散语法)支持不支持
SpEL不支持支持
JSR303数据校验支持不支持
复杂类型封装支持不支持
松散语法

松散语法的意思就是一个属性在配置文件中可以有多个属性名,举个栗子:实体类当中的firstName属性,在配置文件中可以是firstNamefirst-namefirst_name以及FIRST_NAME
@ConfigurationProperties是支持这种命名的,而@Value是不支持的。以firstName为例的测试代码见参考文档

SpEL

SpEL使用#{…}作为定界符, 所有在大括号中的字符都将被认为是SpEL,SpELbean的属性进行动态赋值提供了便利。

复杂类型封装

复杂类型封装指的是,在对象以及Map(如实体中的名字类以及Map<String, Integer> scores)等属性中,用@Value取是取不到值,示例见参考文档。

@ConfigurationProperties用法

spring-boot.version: 2.3.2.RELEASE

dog:
  age: 12
  hobbies: #[吃喝睡, 打豆豆]
    - 吃喝睡
    - 打豆豆
  scores:  #{eq: 90, iq: 85}
    eq: 90
    iq: 85
  groups:  #{one: {num: 2}, two: {len: 4, ok-go: 6}}
    one: {num: 2}
    two: {len: 4, ok-go: 6}
  name:    #{first-name: lao, last-name: liu}
    first-name: lao
    last-name:  liu
  names:   #[{first-name: su, last-name: si},{first-name: se, last-name: xi}]
    - {first-name: su, last-name: si}
    - {first-name: se, last-name: xi}
  friends: #{lila: {first-name: li, last-name: la},xihu: {first-name: xi, last-name: hu}}
    lila: {first-name: li, last-name: la}
    xihu: {first-name: xi, last-name: hu}
@Data
@Configuration
@ConfigurationProperties(prefix = "dog")
public class DogConfigProperties {
    private Integer age;
    private List<String> hobbies;
    private Map<String, Integer> scores;
    private Map<String, Map<String, Integer>> groups;
    private Name name;
    private List<Name> names;
    private Map<String, Name> friends;

    @Data
    public static class Name {
        private String firstName;
        private String lastName;
    }
}

输出结果

DogConfigProperties(age=12, hobbies=[吃喝睡, 打豆豆], scores={iq2=84, eq=90, iq=85}, groups={two={ok-go=6, len=4}, one={num=2}}, name=DogConfigProperties.Name(firstName=lao, lastName=liu), names=[DogConfigProperties.Name(firstName=su, lastName=si), DogConfigProperties.Name(firstName=se, lastName=xi)], friends={lila=DogConfigProperties.Name(firstName=li, lastName=la), xihu=DogConfigProperties.Name(firstName=xi, lastName=hu)})

复杂封装类型如list,map等推荐使用@ConfigurationProperties

@ConfigurationProperties示例源码

@ConfigurationProperties示例源码

激活@ConfigurationProperties的几种方式

有以下几种方法:

  1. 增加注解 @ConfigurationPropertiesScan
  2. 增加注解 @EnableConfigurationProperties(value = [DogConfigProperties::class])
  3. DogConfigProperties类上添加@Component注解进行实例化(本质上与2无区别)
  4. @Configuration 注解的类内手动创建 @Bean
@Configuration
@EnableConfigurationProperties( DogConfigProperties.class )
public class DogConfig {

    @Autowired
    private DogConfigProperties dogConfigProperties;

    @Bean
    public Map dogData() {
        Map map = new HashMap();
        map.put("first name", dogConfigProperties.getName().getFirstName() );
        map.put("age", dogConfigProperties.getAge() );
		// ...
        return map;
    }
}

@Value用法

@Value支持三种取值方式,分别是 字面量,${key}从环境变量、配置文件中获取值,#{SpEL}

  • 没有在配置文件中配置该 key 及其 value 时报错: java.lang.IllegalArgumentException: Could not resolve placeholder 'man.xxx' in value "${man.xxx}"
  • 如果你想要支持不配置 key 程序也能正常运行的话,给其加上默认值:即可
  • 复杂数据类型(Map),必须用SpEL才能解析,语法:#{…},否则报错:
    java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Map': no matching editors or conversion strategy found
@Value基本类型
man.nick: tim
@Value("${man.nick:}")
private String nick;
output: tim

未配置时,nick=“”

@Value列表(不推荐)
man.victors: 44,55,66
@Value("${man.victors:}")
private List<Integer> victors;
output: [44,55,66]

未配置时,victors=[]
低版本需使用EL表达式进行解析:

  • #{'${man.victors:44,55}'.split(',')} ==> output: [44,55]
  • #{'${man.victors:}'.empty ? new String[0] : '${man.victors:}'.split(',')} ==> output: null
@Value Map(不推荐)
man.scores: {'eq': 99, 'iq': 88}
@Value("#{${man.scores:{'eq': 90, 'iq': 85}}}")
private Map<String, Integer> scores;
output: {eq=99, iq=88}

默认值#{${man.scores:{}}} ==> output: null
EL表达式

@Value示例源码

@Value示例源码

参考文档

  1. SpringBoot | @Value 和 @ConfigurationProperties 的区别
  2. SpringBoot之@ConfigurationProperties注解实践
  3. SpringBoot @ConfigurationProperties
  4. 配置文件中Map和List类型如何配置
  5. SpringBoot @Value 读取配置,太强大了!
  6. SpEL表达式总结
  7. SpEL表达式
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: “could not resolve placeholder in value”意思是无法解析占位符的。这通常是因为在配置文件中使用了占位符,但没有提供相应的。解决方法是检查配置文件中的占位符是否正确,并确保提供了相应的。 ### 回答2: 这个错误通常在Spring应用程序中出现,表示应用程序无法解析属性占位符的。 原因可能是属性文件缺失或无法加载,占位符名称拼写错误或属性文件中没有定义,占位符引用了不存在的环境变量等。 要解决这个问题,需要检查以下几个方面: 1. 确保属性文件存在且被正确加载 首先,确认应用程序加载了正确的属性文件,并确保文件名和路径正确。另外,要确保属性文件中的包含在占位符中,并且属性文件中的占位符名称与应用程序中的占位符名称相同。可以使用Spring的PropertyPlaceholderConfigurer或PropertySourcesPlaceholderConfigurer类来加载和解析属性文件。 2. 检查占位符名称的正确拼写 确保占位符名称的拼写正确。如果占位符名称与属性文件中定义的名称不匹配,则应用程序将无法解析属性的。 3. 检查属性文件是否定义了占位符 确保属性文件中定义了占位符,并且占位符名称与应用程序中的占位符名称相同。如果占位符在属性文件中没有定义,应用程序将无法解析属性。 4. 检查占位符是否引用了不存在的环境变量 如果占位符引用了不存在的环境变量,则应用程序将无法解析属性的。因此,应该检查占位符引用的环境变量是否存在。 总的来说,要解决这个问题,需要对应用程序的代码、属性文件和环境变量进行细致的检查,找到导致应用程序无法解析占位符的原因。 ### 回答3: “could not resolve placeholder in value”是Spring框架中常见的错误,通常是由于无法解析属性文件中的占位符导致的。 占位符通常使用${}或者@{}这种格式进行定义,比如在application.properties文件中,我们可能会定义一些占位符来引用一些配置信息,例如: ``` server.port=${my.server.port} ``` 此时,Spring框架会在启动时尝试解析这个占位符,并将${my.server.port}替换为具体的配置。如果Spring无法解析这个占位符,就会抛出“could not resolve placeholder in value”的异常。 这种情况可能由以下原因导致: 1. 属性文件未正确加载:确保属性文件被正确加载,并且文件路径和文件名正确。 2. 占位符错误:检查占位符的格式和拼写是否正确。比如应该使用${},而不是$(),或者占位符中的名称拼写错误。 3. 未正确定义占位符:在属性文件中未定义对应的占位符,或者定义了一个不存在的占位符。 4. 依赖注入错误:如果占位符需要依赖注入来提供,那么可能是依赖注入出现问题导致无法解析占位符。 要解决这个问题,开发者可以采取以下方法: 1. 检查属性文件是否正确加载,并且占位符名称、格式和拼写是否正确。 2. 确认占位符的名称和在属性文件中的定义是否一致,如果不一致需要进行修改。 3. 如果依赖注入出现问题,可以检查依赖的注入是否正确,确定是否需要添加相关依赖。 4. 进行日志输出,观察具体的异常信息和堆栈信息,从中查看详细的错误位置和原因。 总之,在遇到“could not resolve placeholder in value”错误时,需要认真排查并解决问题,以确保程序正常运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值