在SpringBoot工程中,我们常常需要将一些特定前缀的配置项绑定到一个配置类上。这时候我们就可以使用@EnableConfigurationProperties、@ConfigurationProperties注解来实现。在SpringBoot2.2.0中还添加@ConfigurationPropertiesScan注解来帮助我们简化将配置类注册成一个Bean。下面主要讲解这三个注解的使用和源码实现。
现在我有如下的propertoes(yml)文件,里面添加了一些配置信息
#绑定到配置类 com.example.demo.config.MyBatisProperties
mybatis.basePackage= com.example.web.mapper
mybatis.mapperLocations= classpath*:mapper/*.xml
mybatis.typeAliasesPackage= com.example.web.model
mybatis.defaultStatementTimeoutInSecond= 5
mybatis.mapUnderscoreToCamelCase= false
#绑定到配置项类 com.example.demo.config.ShardingProperties
sharding.defaultDSIndex= 0
sharding.dataSources[0].driverClassName= com.mysql.jdbc.Driver
sharding.dataSources[0].jdbcUrl= jdbc:mysql://localhost:3306/lwl_db0?useSSL=false&characterEncoding=utf8
sharding.dataSources[0].username= root
sharding.dataSources[0].password= 123456
sharding.dataSources[0].readOnly= false
@ConfigurationProperties
@ConfigurationProperties注解其实只是指定了配置类中属性所对应的前缀,当一个配置类仅仅被@ConfigurationProperties标记时,配置项的值是不会被绑定其属性的,也不会将其注册为Bean,需要同时使用@Component注解或是@Component子类注解(例如@Configuration)。
@EnableConfigurationProperties
@EnableConfigurationProperties(value={xxx.calss})指定具体的配置类来绑定属性值。主要有两个作用:
- 注册后置处理器ConfigurationPropertiesBindingPostProcessor,用于在Bean被初始化时,给Bean中的属性绑定属性值。这也是为什么第一种方式使用@ConfigurationProperties需要使用@Component注解的原因,否则其不是Bean,无法被Spring处理的后置处理器处理则无法绑定属性值。
- 将一个被标记@ConfigurationProperties的配置类注册为Spring的一个Bean,没有被标记@ConfigurationProperties注解的类不能做为@EnableConfigurationProperties的参数,否则抛出异常。仅仅使用@ConfigurationProperties也不会将这个类注册为一个Bean
@ConfigurationPropertiesScan
在SpringBoot2.2之后,如果想让一个仅有@ConfigurationProperties注解的配置类被注册为bean,可以通过@ConfigurationPropertiesScan注解开启。则不再需要配合@Component一起使用。 实现原理
- 这个注解是使用@Import注解向Spring容器导入org.springframework.boot.context.properties.ConfigurationPropertiesScanRegistrar
- 该类实现了ImportBeanDefinitionRegistrar接口,Spring在启动过程中会回调该接口的方法。
- ConfigurationPropertiesScanRegistrar会通过包扫描,扫描被@ConfigurationProperties标记的类
- 遍历扫描到的标有@ConfigurationProperties类,排除标有@Component类,避免配置类被重复注册,则将其注册为Bean,beanName为prefix+配置类全类名。
- 当配置类注册为 bean 后,@EnableConfigurationProperties注册的后置处理器则可以对其进行属性绑定.
例子
例子一:
例子
例子二:
对于springboot来说都会有这么一个类ServerProperties(读取启动的yml文件) 假如你直接@Autowired直接注入,得到的是一个空(相当于new了一个存新的),需要使用@EnableConfigurationProperties来读取你在yml中的配置
@EnableConfigurationProperties({ServerProperties.class})
@Component
public class PortRuleCompiler implements CommonServiceConstant{
@Autowired
private RequestMappingHandlerMapping mapping;
private final String contextPath;
/** Spring应用上下文环境 */
@Autowired
private ConfigurableListableBeanFactory beanFactory;
@SuppressWarnings("unused")
@Autowired
private RedisInfo redisInfo;
public PortRuleCompiler(ServerProperties serverProperties) {
/**
* spring-boot 旧版本(如1.5.9RELEASE),context-path定义在server.前缀下,
* 高版本定义在server.servlet.前缀下,
* 从 ServerProperties 实例获取 context-path,兼容spring-boot不同的版本,
* 先尝试获取 contextPath字段,如果失败则尝试获取嵌入字段 servlet.contextPath,
* 如果都失败则默认为空字符串,即没有定义context-path
*/
String contextPath;
BeanUtilsBean beanUtils = BeanUtilsBean.getInstance();
try {
contextPath = firstNonNull(beanUtils.getProperty(serverProperties, "contextPath"),"");
}catch (Exception e){
try {
contextPath = firstNonNull(beanUtils.getProperty(serverProperties, "servlet.contextPath"),"");
}catch (Exception e1){
contextPath = "";
}
}
this.contextPath = contextPath;
}
|