一、@ConfigurationProperties注解作用方法

  1. #数据源
  2. spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/jpa
  3. spring.datasource.druid.write.username=root
  4. spring.datasource.druid.write.password=1
  5. spring.datasource.druid.write.driver-class-name=com.mysql.jdbc.Driver
  6. spring.datasource.druid.read.url=jdbc:mysql://localhost:3306/jpa
  7. spring.datasource.druid.read.username=root
  8. spring.datasource.druid.read.password=1
  9. spring.datasource.druid.read.driver-class-name=com.mysql.jdbc.Driver

java代码:

  1. @Configuration
  2. public class DruidDataSourceConfig {
  3. /**
  4. * DataSource 配置
  5. * @return
  6. */
  7. @ConfigurationProperties(prefix = "spring.datasource.druid.read")
  8. @Bean(name = "readDruidDataSource")
  9. public DataSource readDruidDataSource() {
  10. return new DruidDataSource();
  11. }
  12. /**
  13. * DataSource 配置
  14. * @return
  15. */
  16. @ConfigurationProperties(prefix = "spring.datasource.druid.write")
  17. @Bean(name = "writeDruidDataSource")
  18. @Primary
  19. public DataSource writeDruidDataSource() {
  20. return new DruidDataSource();
  21. }
  22. }

也许有的人看到这里会比较疑惑,prefix并没有指定配置的全限定名,那它是怎么进行配置绑定的呢?

相信大家肯定了解@Value注解,它可以通过全限定名进行配置的绑定,这里的ConfigurationProperties其实就类似于使用多个@Value同时绑定,绑定的对象就是DataSource类型的对象,而且是 隐式绑定 的,意味着在配置文件编写的时候需要与对应类的字段名称 相同.比如上述spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/jpa

当然了,你也可以随便写个配置,比如spring.datasource.druid.write.uuu=www.baidu.com,此时你只需要在注解中加上以下参数即可
10-Spring-配置属性自定义转换用法 - 图1
以上就完成了多个数据源的配置,为读写分离做了铺垫

二、@ConfigurationProperties注解作用类

配置文件:

  1. spring.datasource.url=jdbc:mysql://127.0.0.1:8888/test?useUnicode=false&autoReconnect=true&characterEncoding=utf-8
  2. spring.datasource.username=root
  3. spring.datasource.password=root
  4. spring.datasource.driver-class-name=com.mysql.jdbc.Driver
  5. spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

java代码:

  1. @ConfigurationProperties(prefix = "spring.datasource")
  2. @Component
  3. public class DatasourcePro {
  4. private String url;
  5. private String username;
  6. private String password;
  7. // 配置文件中是driver-class-name, 转驼峰命名便可以绑定成
  8. private String driverClassName;
  9. private String type;
  10. }

用法

  1. @Controller
  2. @RequestMapping(value = "/config")
  3. public class ConfigurationPropertiesController {
  4. @Autowired
  5. private DatasourcePro datasourcePro;
  6. @RequestMapping("/test")
  7. @ResponseBody
  8. public Map<String, Object> test(){
  9. Map<String, Object> map = new HashMap<>();
  10. map.put("url", datasourcePro.getUrl());
  11. map.put("userName", datasourcePro.getUsername());
  12. map.put("password", datasourcePro.getPassword());
  13. map.put("className", datasourcePro.getDriverClassName());
  14. map.put("type", datasourcePro.getType());
  15. return map;
  16. }
  17. }
  1. @ConfigurationProperties 和 @value 有着相同的功能,但是 @ConfigurationProperties的写法更为方便
  2. @ConfigurationProperties 的 POJO类的命名比较严格,因为它必须和prefix的后缀名要一致, 不然值会绑定不上, 特殊的后缀名是“driver-class-name”这种带横杠的情况,在POJO里面的命名规则是 下划线转驼峰 就可以绑定成功,所以就是 “driverClassName”

三、配置属性自定义转换

当我们通过@ConfigurationProperties注解实现配置 bean的时候,如果默认的配置属性转换无法满足我们的需求的时候,我们可以根据自己的需求通过以下扩展方式对配置属性进行转换。

PropertyEditorSupport实现

下面的例子是把属性中定义的字符串转换成Movie,并且把name的值大写

  • 继承PropertyEditorSupport并且实现PropertyEditorRegistrar接口

    1. public class CustomMovieEditor extends PropertyEditorSupport implements PropertyEditorRegistrar {
    2. @Override
    3. public String getAsText() {
    4. Movie movie = (Movie) getValue();
    5. return movie == null ? "" : movie.getName();
    6. }
    7. @Override
    8. public void setAsText(String text) throws IllegalArgumentException {
    9. System.out.println("继承[PropertyEditorSupport]类,转换数据=" + text);
    10. String[] data = text.split("-");
    11. Movie movie = new Movie(data[0].toUpperCase(), Integer.parseInt(data[1]));
    12. setValue(movie);
    13. }
    14. @Override
    15. public void registerCustomEditors(PropertyEditorRegistry registry) {
    16. registry.registerCustomEditor(Movie.class, this);
    17. }
    18. }

    注册自定义的PropertyEditor

    1. @Bean
    2. public CustomEditorConfigurer customEditorConfigurer() {
    3. CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
    4. // 有两种注册方式 这是第一种
    5. customEditorConfigurer.setPropertyEditorRegistrars(
    6. new PropertyEditorRegistrar[]{ new CustomMovieEditor() });
    7. // 第二 种
    8. Map<Class<?>,Class<? extends PropertyEditor>> maps = new HashMap<>();
    9. maps.put(Movie.class,CustomMovieEditor.class);
    10. return customEditorConfigurer;
    11. }

    其中Movie类: ```java @Setter @Getter @AllArgsConstructor public class Movie {

    private String name;

    private Integer seat;

}

  1. 需要进行自定义属性类型转换的类:
  2. ```java
  3. @Data
  4. @ConfigurationProperties(prefix = "huanghe")
  5. @Component
  6. public class TestMovieProperties {
  7. String name;
  8. Movie movie;
  9. }

启动测试类:

  1. @RestController
  2. public class ProductController_Consumer {
  3. @Autowired
  4. private TestMovieProperties movieProperties;
  5. @RequestMapping(value = "/consumer/product/get/{id}")
  6. public String get(@PathVariable("id") Long id) {
  7. System.out.println(movieProperties);
  8. return "demo";
  9. }
  10. }

会发现Movie的属性已经注册进去了。这种自定义属性配置自定义转换,适用@ConfigurationProperties注解实现配置 bean的时候,如果默认的配置属性转换无法满足我们的需求的时候,我们可以根据自己的需求通过以下扩展方式对配置属性进行转换。

Converter接口+@ConfigurationPropertiesBinding注解

使用案例:https://www.dazhuanlan.com/zhangxiaohai/topics/1506334

  1. //注意
  2. @Component
  3. @ConfigurationPropertiesBinding
  4. public class StringToPersonConverter implements Converter<String, Person> {
  5. @Override
  6. public Person convert(String from) {
  7. log.info("使用[Converter]接口,转换数据={}", from);
  8. String[] data = from.split(",");
  9. return Person.builder().name(data[0]).age(Integer.parseInt(data[1])).build();
  10. }
  11. }

总结

  • 以上两种实现方式结果,但是Converter接口相比PropertyEditor接口更加灵活一些,PropertyEditor接口仅限于String转换,Converter可以自定义别的,并且PropertyEditor接口通常用于Controller中的接收参数的转换。
  • @ConfigurationPropertiesBinding是限定符注解@Qualifier的派生类而已,参考org.springframework.boot.context.properties.ConversionServiceDeducer,以下是源代码片段 ```java @Autowired(required = false) @ConfigurationPropertiesBinding public void setConverters(List> converters) {
    1. this.converters = converters;
    }

/**

  • A list of custom converters (in addition to the defaults) to use when
  • converting properties for binding.
  • @param converters the converters to set */ @Autowired(required = false) @ConfigurationPropertiesBinding public void setGenericConverters(List converters) { this.genericConverters = converters; } ```
  • Formatter接口是不能对属性完成转换的,因为ConversionServiceDeducer初始化的时候只获取GenericConverterConverter接口
  • 官方文档上还介绍了可以使用实现org.springframework.core.convert.ConversionService并且Bean名称也必须叫conversionService,不过大部分情况不推荐自己通过这种方式去实现这个接口,因为自己实现的ConversionService会替代默认的。具体参考ConversionServiceDeducer源码:

四、基于XML配置的方式

http://www.what21.com/sys/view/java_spring-java_1456896197847.html
https://blog.csdn.net/u010675669/article/details/86488575