一、@ConfigurationProperties注解作用方法
#数据源spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/jpaspring.datasource.druid.write.username=rootspring.datasource.druid.write.password=1spring.datasource.druid.write.driver-class-name=com.mysql.jdbc.Driverspring.datasource.druid.read.url=jdbc:mysql://localhost:3306/jpaspring.datasource.druid.read.username=rootspring.datasource.druid.read.password=1spring.datasource.druid.read.driver-class-name=com.mysql.jdbc.Driver
java代码:
@Configurationpublic class DruidDataSourceConfig {/*** DataSource 配置* @return*/@ConfigurationProperties(prefix = "spring.datasource.druid.read")@Bean(name = "readDruidDataSource")public DataSource readDruidDataSource() {return new DruidDataSource();}/*** DataSource 配置* @return*/@ConfigurationProperties(prefix = "spring.datasource.druid.write")@Bean(name = "writeDruidDataSource")@Primarypublic DataSource writeDruidDataSource() {return new DruidDataSource();}}
也许有的人看到这里会比较疑惑,prefix并没有指定配置的全限定名,那它是怎么进行配置绑定的呢?
相信大家肯定了解@Value注解,它可以通过全限定名进行配置的绑定,这里的ConfigurationProperties其实就类似于使用多个@Value同时绑定,绑定的对象就是DataSource类型的对象,而且是 隐式绑定 的,意味着在配置文件编写的时候需要与对应类的字段名称 相同.比如上述spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/jpa
当然了,你也可以随便写个配置,比如spring.datasource.druid.write.uuu=www.baidu.com,此时你只需要在注解中加上以下参数即可
以上就完成了多个数据源的配置,为读写分离做了铺垫
二、@ConfigurationProperties注解作用类
配置文件:
spring.datasource.url=jdbc:mysql://127.0.0.1:8888/test?useUnicode=false&autoReconnect=true&characterEncoding=utf-8spring.datasource.username=rootspring.datasource.password=rootspring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.type=com.alibaba.druid.pool.DruidDataSource
java代码:
@ConfigurationProperties(prefix = "spring.datasource")@Componentpublic class DatasourcePro {private String url;private String username;private String password;// 配置文件中是driver-class-name, 转驼峰命名便可以绑定成private String driverClassName;private String type;}
用法
@Controller@RequestMapping(value = "/config")public class ConfigurationPropertiesController {@Autowiredprivate DatasourcePro datasourcePro;@RequestMapping("/test")@ResponseBodypublic Map<String, Object> test(){Map<String, Object> map = new HashMap<>();map.put("url", datasourcePro.getUrl());map.put("userName", datasourcePro.getUsername());map.put("password", datasourcePro.getPassword());map.put("className", datasourcePro.getDriverClassName());map.put("type", datasourcePro.getType());return map;}}
- @ConfigurationProperties 和 @value 有着相同的功能,但是 @ConfigurationProperties的写法更为方便
- @ConfigurationProperties 的 POJO类的命名比较严格,因为它必须和prefix的后缀名要一致, 不然值会绑定不上, 特殊的后缀名是“driver-class-name”这种带横杠的情况,在POJO里面的命名规则是 下划线转驼峰 就可以绑定成功,所以就是 “driverClassName”
三、配置属性自定义转换
当我们通过@ConfigurationProperties注解实现配置 bean的时候,如果默认的配置属性转换无法满足我们的需求的时候,我们可以根据自己的需求通过以下扩展方式对配置属性进行转换。
PropertyEditorSupport实现
下面的例子是把属性中定义的字符串转换成Movie,并且把name的值大写
继承PropertyEditorSupport并且实现PropertyEditorRegistrar接口
public class CustomMovieEditor extends PropertyEditorSupport implements PropertyEditorRegistrar {@Overridepublic String getAsText() {Movie movie = (Movie) getValue();return movie == null ? "" : movie.getName();}@Overridepublic void setAsText(String text) throws IllegalArgumentException {System.out.println("继承[PropertyEditorSupport]类,转换数据=" + text);String[] data = text.split("-");Movie movie = new Movie(data[0].toUpperCase(), Integer.parseInt(data[1]));setValue(movie);}@Overridepublic void registerCustomEditors(PropertyEditorRegistry registry) {registry.registerCustomEditor(Movie.class, this);}}
注册自定义的PropertyEditor
@Beanpublic CustomEditorConfigurer customEditorConfigurer() {CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();// 有两种注册方式 这是第一种customEditorConfigurer.setPropertyEditorRegistrars(new PropertyEditorRegistrar[]{ new CustomMovieEditor() });// 第二 种Map<Class<?>,Class<? extends PropertyEditor>> maps = new HashMap<>();maps.put(Movie.class,CustomMovieEditor.class);return customEditorConfigurer;}
其中Movie类: ```java @Setter @Getter @AllArgsConstructor public class Movie {
private String name;
private Integer seat;
}
需要进行自定义属性类型转换的类:```java@Data@ConfigurationProperties(prefix = "huanghe")@Componentpublic class TestMovieProperties {String name;Movie movie;}
启动测试类:
@RestControllerpublic class ProductController_Consumer {@Autowiredprivate TestMovieProperties movieProperties;@RequestMapping(value = "/consumer/product/get/{id}")public String get(@PathVariable("id") Long id) {System.out.println(movieProperties);return "demo";}}
会发现Movie的属性已经注册进去了。这种自定义属性配置自定义转换,适用@ConfigurationProperties注解实现配置 bean的时候,如果默认的配置属性转换无法满足我们的需求的时候,我们可以根据自己的需求通过以下扩展方式对配置属性进行转换。
Converter接口+@ConfigurationPropertiesBinding注解
使用案例:https://www.dazhuanlan.com/zhangxiaohai/topics/1506334
//注意@Component@ConfigurationPropertiesBindingpublic class StringToPersonConverter implements Converter<String, Person> {@Overridepublic Person convert(String from) {log.info("使用[Converter]接口,转换数据={}", from);String[] data = from.split(",");return Person.builder().name(data[0]).age(Integer.parseInt(data[1])).build();}}
总结
- 以上两种实现方式结果,但是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) {
}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初始化的时候只获取GenericConverter和Converter接口
- 官方文档上还介绍了可以使用实现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
