前言

用springboot开发的过程中,我们会用到@ConfigurationProperties注解,主要是用来把properties或者yml配置文件转化为bean来使用的,而@EnableConfigurationProperties注解的作用是@ConfigurationProperties注解生效。 如果只配置@ConfigurationProperties注解,在IOC容器中是获取不到properties配置文件转化的bean的,当然在@ConfigurationProperties加入注解的类上加@Component也可以使交于springboot管理。

举个栗子

第一步:创建一个类TestConfigurationProperties

@ConfigurationProperties(prefix = "properties")
public class TestConfigurationProperties {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}
复制代码

注意:得加上set和get方法
第二步:创建TestAutoConfiguration类

@Configuration
@EnableConfigurationProperties(TestConfigurationProperties.class)
public class TestAutoConfiguration {private TestConfigurationProperties testConfigurationProperties;public TestAutoConfiguration(TestConfigurationProperties testConfigurationProperties) {this.testConfigurationProperties = testConfigurationProperties;}@Beanpublic User user(){User user = new User();user.setName(testConfigurationProperties.getName());return user;}
}
复制代码

注意:得创建一个有参构造方法
第三步:配置文件加入属性

properties.name=test
复制代码

第四步:跑一下,打印出User这个类

@RestController
@RequestMapping("/api/test")
@Slf4j
public class TestController {@AutowiredTestConfigurationProperties testConfigurationProperties;@AutowiredUser user;@RequestMapping(value = "/testConfigurationProperties")public String testConfigurationProperties() {log.info("test testConfigurationProperties.............{}", testConfigurationProperties.getName());log.info("user:{}", user);return "SUCCESS";}
}
复制代码

控制台输出:

2019-04-21/16:11:36.638||||||||^_^|[http-nio-8088-exec-1] INFO  com.stone.zplxjj.controller.TestController 37 - test testConfigurationProperties.............test
2019-04-21/16:11:36.639||||||||^_^|[http-nio-8088-exec-1] INFO  com.stone.zplxjj.controller.TestController 38 - user:User(id=null, name=test)
复制代码

@EnableConfigurationProperties是怎么加载的

通过查看@EnableConfigurationProperties的注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EnableConfigurationPropertiesImportSelector.class)
public @interface EnableConfigurationProperties {/*** Convenient way to quickly register {@link ConfigurationProperties} annotated beans* with Spring. Standard Spring Beans will also be scanned regardless of this value.* @return {@link ConfigurationProperties} annotated beans to register*/Class<?>[] value() default {};}
复制代码

通过分析自动配置可以知道,肯定是这个类EnableConfigurationPropertiesImportSelector起的作用:

private static final String[] IMPORTS = {ConfigurationPropertiesBeanRegistrar.class.getName(),ConfigurationPropertiesBindingPostProcessorRegistrar.class.getName() };@Overridepublic String[] selectImports(AnnotationMetadata metadata) {return IMPORTS;}
复制代码

selectImports方法返回了这两个类:ConfigurationPropertiesBeanRegistrar和ConfigurationPropertiesBindingPostProcessorRegistrar,是何时加载的,我们只需要看这个类ConfigurationPropertiesBeanRegistrar即可:

public static class ConfigurationPropertiesBeanRegistrarimplements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry) {getTypes(metadata).forEach((type) -> register(registry,(ConfigurableListableBeanFactory) registry, type));}//找到加入这个注解@EnableConfigurationProperties里面的value值,其实就是类classprivate List<Class<?>> getTypes(AnnotationMetadata metadata) {MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(EnableConfigurationProperties.class.getName(), false);return collectClasses((attributes != null) ? attributes.get("value"): Collections.emptyList());}private List<Class<?>> collectClasses(List<?> values) {return values.stream().flatMap((value) -> Arrays.stream((Object[]) value)).map((o) -> (Class<?>) o).filter((type) -> void.class != type).collect(Collectors.toList());}//注册方法:根据找到的类名name和type,将加入注解@ConfigurationProperties的类加入spring容器里面private void register(BeanDefinitionRegistry registry,ConfigurableListableBeanFactory beanFactory, Class<?> type) {String name = getName(type);if (!containsBeanDefinition(beanFactory, name)) {registerBeanDefinition(registry, name, type);}}//找到加入注解@ConfigurationProperties的类的名称,加入一定格式的拼接private String getName(Class<?> type) {ConfigurationProperties annotation = AnnotationUtils.findAnnotation(type,ConfigurationProperties.class);String prefix = (annotation != null) ? annotation.prefix() : "";return (StringUtils.hasText(prefix) ? prefix + "-" + type.getName(): type.getName());}private boolean containsBeanDefinition(ConfigurableListableBeanFactory beanFactory, String name) {if (beanFactory.containsBeanDefinition(name)) {return true;}BeanFactory parent = beanFactory.getParentBeanFactory();if (parent instanceof ConfigurableListableBeanFactory) {return containsBeanDefinition((ConfigurableListableBeanFactory) parent,name);}return false;}private void registerBeanDefinition(BeanDefinitionRegistry registry, String name,Class<?> type) {assertHasAnnotation(type);GenericBeanDefinition definition = new GenericBeanDefinition();definition.setBeanClass(type);registry.registerBeanDefinition(name, definition);}private void assertHasAnnotation(Class<?> type) {Assert.notNull(AnnotationUtils.findAnnotation(type, ConfigurationProperties.class),() -> "No " + ConfigurationProperties.class.getSimpleName()+ " annotation found on  '" + type.getName() + "'.");}}
复制代码

结语

另外还有这个类:ConfigurationPropertiesBindingPostProcessorRegistrar,刚刚没有分析,看了下源码,其实他做的事情就是将配置文件当中的属性值赋予到加了@ConfigurationProperties的注解的类的属性上,具体就不分析了,有兴趣自己可以阅读,入口知道了,就简单了

本人也开通了微信公众号:stonezplxjj和个人博客:www.zplxjj.com,更多文章欢迎关注公众号:

转载于:https://juejin.im/post/5cbeaa26e51d45789024d7e2

springboot(四)——@EnableConfigurationProperties是如何起作用的你知道吗相关推荐

  1. SpringBoot之@EnableConfigurationProperties分析

    我们在用SpringBoot进行项目开发的时候,基本上都使用过@ConfigurationProperties这个注解,我们在之前的文章中也说过ConfigurationPropertiesBindi ...

  2. java 切面 不执行,解决springboot的aop切面不起作用问题(失效的排查)

    检查下springboot的启动类是否开启扫描 @springbootapplication @componentscan(basepackages = {"com.zhangpu.spri ...

  3. SpringBoot(四) Web开发(2)Restful风格的CRUD操作

    1.创建工程 使用之前使用的Spring提供的向导,快速创建一个包含web模板的SpringBoot工程:springboot-web-restful: 1.1 pom.xml如下 <?xml ...

  4. springboot工程中各个层次的作用+springboot连接数据库的工具汇总+Mybatis的开发方式/语法

    下面这个是hibernate的相关工程 下面这个是Mybatis的相关工程 \ 可以看出无论使用哪一种,方式都是一致的. --------------------------------------- ...

  5. Spring-Boot (四) 集成Spring Security

    为什么80%的码农都做不了架构师?>>>    http://nealma.com/2016/04/30/spring-boot-4-security/ ### 前言     shi ...

  6. apache shiro版本查看_深入学习SpringBoot(四):springboot整合shiro

    shiro是一个权限框架,具体的使用可以查看其官网 http://shiro.apache.org/ 它提供了很方便的权限认证和登录的功能. 而springboot作为一个开源框架,必然提供了和shi ...

  7. SpringBoot (四):JPA(多表关联查询)

    Spring Boot Jpa 是 Spring 基于 ORM 框架.Jpa 规范的基础上封装的一套 Jpa 应用框架,可使开发者用极简的代码即可实现对数据的访问和操作.它提供了包括增删改查等在内的常 ...

  8. SpringBoot (四) :SpringBoot整合使用JdbcTemplate

    什么是JdbcTemplate 为了使 JDBC 更加易于使用,Spring 在 JDBCAPI 上定义了一个抽象层, 以此建立一个JDBC存取框架. 作为 SpringJDBC 框架的核心, JDB ...

  9. Spring Boot学习总结(11)——SpringBoot的Starter依赖包及作用

    1. spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置.日志和YAML. 2. spring-boot-starter-amqp 通过spring-rab ...

最新文章

  1. 程序员们请收好这本JVM日历:Java 2018大事回顾
  2. python 为什么只执行一次_python只执行一次
  3. iTween for Unity
  4. 跨域iframe高度自适应(兼容IE/FF/OP/Chrome)
  5. POJ--3278 Catch That Cow
  6. 【OpenCV4】fatal error: opencv2/core.hpp: No such file or directory 解决方法
  7. 虎牙直播电影一天收入_电影收入
  8. QNX系统的IDE拷贝文件
  9. uniapp 安卓ios端热更新
  10. java将Word转换成PDF
  11. ASIC和FPGA设计流程
  12. 《大话设计模式》读后感
  13. js为li列表添加点击事件
  14. maven install 提示:Process terminated
  15. C语言基础编程(switch语句)
  16. AWS助初创企业扬帆远航
  17. 史上最小 x86 Linux 模拟器「GitHub 热点速览 v.22.50」
  18. 上海水务局智慧水务解决方案
  19. 【Android】Scheme详解
  20. 游戏SDK到底是什么?

热门文章

  1. matlab max报错,奇怪的报错。未定义'*'
  2. 94级计算机科学,清华大学计算机科学与技术系
  3. 恐龙快跑小程序对接流量主源码+前端 v5.0.4 全开源微擎框架
  4. KODExplorer可道云-资源管理器(芒果云)
  5. multism中ui和uo应该怎么表示_Excel中VBA程序基本语法之强大的数组,了解数组的功能...
  6. imap服务器appleimap.163.com没有响应,163smtp
  7. HTML粘性滑块导航源码-可用来做首页
  8. .net 代码混淆原理性实践
  9. DataGrid 导出到 Excel 的帮助类
  10. Node.js: 深入浅出Nodejs读书笔记