【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 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表达式

你可能感兴趣的:(SpringBoot,spring,boot,注入配置)