003SpringBoot之@ConfigurationProp

作者: 编程界的小学生 | 来源:发表于2018-05-22 19:04 被阅读33次

    一、两个注解对比

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

    注意:配置文件不管是yml格式还是properties格式,上面两种注解都可以获取的到。

    二、来源

    package org.springframework.boot.context.properties.ConfigurationProperties {}
    
    package org.springframework.beans.factory.annotation.Value {}
    

    三、功能

    1、@ConfigurationProperties

    指定一个前缀,将配置文件里前缀后面的所有属性都一一映射到JavaBean对应的属性中。

    比如:

    配置:

    person:
      lastName: 张三
      age: 25
      isBoss: false
      birth: 2017/12/12
      maps: {key1: value1,key2: value2}
      lists:
        - 雷军
        - 乔布斯
        - 马云
      dog:
        name: milly
        age: 2
    

    JavaBean:

    @ConfigurationProperties(prefix = "person")
    @Component
    public class Person {
        // 这种驼峰写法在yml里可以用lastName或者last-name,都可以
        private String lastName;
        private Integer age;
        private boolean isBoss;
        private Date birth;
    
        private Map<String, Object> maps;
        private List<Object> lists;
        private Dog dog;
        ...省略getter/setter/toString...
    }
    

    PS:需要将Person指定为SpringBean,@ConfigurationProperties才会生效。

    测试类:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class Springboot02ConfigApplicationTests {
    
        @Autowired
        private Person person;
    
        @Test
        public void contextLoads() {
            System.out.println(person);
        }
    }
    

    测试结果:

    Person{lastName='张三', age=25, isBoss=false, birth=Tue Dec 12 00:00:00 CST 2017, maps={key1=value1, key2=value2}, lists=[雷军, 乔布斯, 马云], dog=Dog{name='milly', age=2}}
    

    PS:结果发现我们配置文件里的属性值都赋值到了JavaBean中,符合预期。

    2、@Value

    类似于Spring配置文件的value属性:

    <bean class="Person">
        <property name="lastName" value="zhangsan"></property>
    </bean>
    

    要想完成JavaBean和配置文件的映射,需要在JavaBean中的每个属性上都写上@Value,进行一一匹配。

    配置:

    同@ConfigurationProperties的配置
    

    JavaBean:

    @Component
    public class Person {
        @Value("person.lastName")
        private String lastName;
        @Value("person.age")
        private Integer age;
        @Value("person.isBoss")
        private boolean isBoss;
        private Date birth;
    
        private Map<String, Object> maps;
        private List<Object> lists;
        private Dog dog;
        ...省略getter/setter/toString...
    }
    

    PS:只写了前几个,效果很明显,我们需要写很多@Value注解,在每个属性上都写上,很麻烦。

    测试类:

    同@ConfigurationProperties的配置
    

    四、松散绑定

    1、定义

    比如JavaBean里写的是lastName(驼峰写法),配置文件里可以写成lastName,也可以写成last-name。

    2、证明

    2.1、@ConfigurationProperties

    配置:

    person:
      last-name: 张三
    

    JavaBean:

    @ConfigurationProperties(prefix = "person")
    @Component
    public class Person {
        // 这种驼峰写法在yml里可以用lastName或者last-name,都可以
        private String lastName;
    }
    

    运行测试类, 依然可以正常赋值。

    2.2、@Value

    配置:

    person:
      last-name: 张三
    

    JavaBean:

    @Component
    public class Person {
        @Value("${person.lastName}")
        private String lastName;
    }
    

    运行测试类,启动会报错

    Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'person.lastName' in value "${person.lastName}"
    

    五、SpEL

    1、@ConfigurationProperties

    不支持SpEL表达式,比如年龄字段若写成:#{22 * 2},会出错。

    2、@Value

    支持SpEL表达式,比如:

    @Component
    public class Person {
        @Value("#{22*2}")
        private Integer age;
    }
    

    输出年龄:44

    六、JSR303数据校验

    1、@ConfigurationProperties

    配置:

    person:
      lastName: 张三
      age: 25
      isBoss: false
      birth: 2017/12/12
      maps: {key1: value1,key2: value2}
      lists:
        - 雷军
        - 乔布斯
        - 马云
      dog:
        name: milly
        age: 2
    

    JavaBean:

    @ConfigurationProperties(prefix = "person")
    @Component
    @Validated
    public class Person {
        @Email
        private String lastName;
        private Integer age;
        private boolean isBoss;
        private Date birth;
    
        private Map<String, Object> maps;
        private List<Object> lists;
        private Dog dog;
        ...省略getter/setter/toString...
    }
    

    测试结果:

    - Field error in object 'person' on field 'lastName': rejected value [张三]; codes [Email.person.lastName,Email.lastName,Email.java.lang.String,Email]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [person.lastName,lastName]; arguments []; default message [lastName],[Ljavax.validation.constraints.Pattern$Flag;@54336c81,org.springframework.validation.beanvalidation.SpringValidatorAdapter$ResolvableAttribute@1556f2dd]; default message [不是一个合法的电子邮件地址]; origin class path resource [application.yml]:6:14
    

    2、@Value

    配置:

    同@ConfigurationProperties的配置
    

    JavaBean:

    @Component
    @Validated
    public class Person {
        @Email
        @Value("${person.last-name}")
        private String lastName;
        private Integer age;
        private boolean isBoss;
        private Date birth;
    
        private Map<String, Object> maps;
        private List<Object> lists;
        private Dog dog;
        ...省略getter/setter/toString...
    }
    

    测试结果:

    不会出现异常
    

    七、复杂类型封装

    1、什么是复杂类型?

    比如person里有个maps

    2、@ConfigurationProperties

    配置:

    person:
      maps: {key1: value1,key2: value2}
    

    JavaBean:

    @ConfigurationProperties(prefix = "person")
    @Component
    public class Person {
        private Map<String, Object> maps;
    }
    

    运行结果:会正常给maps赋值。

    3、@Value

    配置:

    person:
      maps: {key1: value1,key2: value2}
    

    JavaBean:

    @Component
    public class Person {
        @Value("${person.maps}")
        private Map<String, Object> maps;
    }
    

    运行结果:

    Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'person.mps' in value "${person.mps}"
    

    八、建议

    1、如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value。简单粗暴。

    2、如果说,我们专门编写了一个JavaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties注解进行映射。

    九、广告

    • QQ群【Java初学者学习交流群】:458430385

    • 微信公众号【Java码农社区】

    img
    • 今日头条号:编程界的小学生

    相关文章

      网友评论

        本文标题:003SpringBoot之@ConfigurationProp

        本文链接:https://www.haomeiwen.com/subject/yeykjftx.html