创建自己的自动配置

当你的应用需要以jar包的形式提供给其它应用使用时,可以考虑把它们封装为一个Spring Boot Starter。即该jar包是可以自动添加需要引用的依赖项,也能够对核心功能进行自动配置。自动配置的核心类是一个标注了@Configuration的类,然后在自动配置类中可以定义相应的bean。比如下面的配置类中定义了一个HelloBean类型的bean。

@Configuration
public class HelloAutoConfiguration {@Beanpublic HelloBean helloBean() {return new HelloBean();}}

然后需要在Classpath下的META-INF/spring.factories中以org.springframework.boot.autoconfigure.EnableAutoConfiguration为Key,以对应的自动配置类为Value进行配置,如果有多个自动配置类,多个自动配置类之间可以以英文逗号分隔。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.elim.autoconfigure.HelloAutoConfiguration

Spring Boot在启动时将读取Classpath下META-INF/spring.factories中Key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的配置类,将它们进行实例化。所以经过上述配置后,系统启动后将自动创建HelloBean类型的bean。

自动配置类通常不会像上面那样直接进行定义,而是会添加一些附加条件,比如在Classpath中拥有某些Class才生效,或者需要bean容器中不存在指定bean时才生效等等。Spring Boot为它们提供了一系列的@ConditionalXXX,常用的如下:

  • ConditionalOnClass :用于指定在Classpath下拥有某些Class时才生效
  • ConditionalOnMissingClass :用于指定在Classpath下不存在某些Class时才生效
  • ConditionalOnBean :用于指定在bean容器中存在某些bean时生效
  • ConditionalOnMissingBean :用于指定在bean容器中不存在某些bean时生效
  • ConditionalOnWebApplication :用于指定当应用是Web应用时生效
  • ConditionalOnNotWebApplication :用于指定当应用是非Web应用时生效
  • ConditionalOnProperty :用于指定当配置了某些特定的参数时生效
  • ConditionalOnExpression :用于根据SpEl表达式控制是否生效
  • ConditionalOnSingleCandidate :用于指定当bean容器中只存在唯一的指定类型的bean时才生效;当bean容器中存在多个指定类型的bean,但是使用@Primary指定了主候选者也是可以匹配的,即也是生效的

更多可用的Conditional注解可以参考API文档的org.springframework.boot.autoconfigure.condition包。

下面的代码中指定了当Classpath下存在Hello.class,且bean容器中不存在HelloBean类型的bean时下面的配置类将生效。

@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
public class HelloAutoConfiguration {@Beanpublic HelloBean helloBean() {return new HelloBean();}}

这些条件配置注解也是可以添加到bean上的。比如下面代码中指定了当Environment中存在Key为autoconfigure.hello.enabled属性且其值为true时将创建HelloBean类型的bean,或者当Environment中不存在Key为autoconfigure.hello.enabled属性时也将创建HelloBean类型的bean(由matchIfMissing控制)。所以针对下面的配置,默认情况下是会创建HelloBean类型的bean的,如果不期望创建该类型的bean,可以在application.properties文件中指定autoconfigure.hello.enabled=false

@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
public class HelloAutoConfiguration {@Bean@ConditionalOnProperty(prefix = "autoconfigure.hello", name = "enabled", havingValue = "true", matchIfMissing = true)public HelloBean helloBean() {return new HelloBean();}}

当使用@ConditionalOnProperty时如果对应的值的可选值是true/false,可以不指定havingValue属性,此时只要值不为false,都会认为是true。

绑定参数

通常自定义的Starter会需要依靠外部配置的属性进行一些自动配置。此时可以使用@ConfigurationProperties标注在用来接收属性的Class上,它可以指定一个前缀,然后将在application.properties中寻找指定前缀和字段名称组合起来的属性进行绑定。比如下面的属性类中的name属性将绑定application.properties中定义的autoconfigure.hello.name属性的值。

@Data
@ConfigurationProperties("autoconfigure.hello")
public class HelloProperties {private String name;private String message;}

@ConfigurationProperties标注的Class需要通过在配置类上使用@EnableConfigurationProperties进行启用。@EnableConfigurationProperties指定的配置类会自动注册为Spring bean容器中的一个bean,然后可以在配置类中自动注入对应的属性类。比如下面的代码中在HelloAutoConfiguration类上通过@EnableConfigurationProperties(HelloProperties.class)指定了启用HelloProperties这个属性配置类,然后把它定义为HelloAutoConfiguration类中的一个属性,并标注为自动注入,然后在定义HelloBean类型的bean时从HelloProperties中获取属性值进行配置。

@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
@EnableConfigurationProperties(HelloProperties.class)
public class HelloAutoConfiguration {@Autowiredprivate HelloProperties helloProperties;@Bean@ConditionalOnProperty(prefix = "autoconfigure.hello", name = "enabled", matchIfMissing = true)public HelloBean helloBean() {HelloBean helloBean = new HelloBean();helloBean.setName(helloProperties.getName());return helloBean;}}

上面的代码中定义HelloBean时从HelloProperties中获取name属性赋值给了HelloBean对象的name属性。这样的需求其实可以直接通过@ConfigurationProperties给HelloBean的name属性赋值,而不必添加多余的HelloProperties类。把@ConfigurationProperties定义在HelloBean定义的方法上可以拥有相同的效果,比如下面这样。

@Configuration
@ConditionalOnClass(Hello.class)
@ConditionalOnMissingBean(HelloBean.class)
public class HelloAutoConfiguration {@Bean@ConditionalOnProperty(prefix = "autoconfigure.hello", name = "enabled", matchIfMissing = true)@ConfigurationProperties("autoconfigure.hello")public HelloBean helloBean() {return new HelloBean();}}

使用@ConfigurationProperties定义属性配置类时最好定义的前缀不要以spring开头,以免跟未来Spring官方提供的属性配置类存在冲突。

自定义的Starter在命名时不要命名为spring-boot-starter-xxx,可以命名为xxx-spring-boot-starterspring-boot-starter-xxx留给官方使用。

参考文档

https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/html/boot-features-developing-auto-configuration.html

(注:本文基于Spring Boot 2.0.3所写)

Spring Boot(04)——创建自己的自动配置相关推荐

  1. Spring Boot面试必问:自动配置原理

    Spring Boot自动配置原理 在传统的SSM框架集成中,需要编写大量的XML配置文件,比如集成Mybatis时,需要编写mybatis_config.xml文件,在集成springmvc时,需要 ...

  2. Spring Boot 到底是怎么做到自动配置的?

    作者:祖大帅 juejin.im/post/5b679fbc5188251aad213110 SpringBoot的故事从一个面试题开始 Spring Boot.Spring MVC 和 Spring ...

  3. 阿里微服务专家自己手写Spring Boot 实现一个简单的自动配置模块

    为了更好的理解 Spring Boot 的 自动配置和工作原理,我们自己来实现一个简单的自动配置模块. 假设,现在项目需要一个功能,需要自动记录项目发布者的相关信息,我们如何通过 Spring Boo ...

  4. Spring Boot + JSP 创建web项目

    虽然Spring Boot的官网不推荐使用JSPs,但是本篇文章还是带你实现Spring Boot + JSP创建一个简单的web项目.想要用Spring Boot + Thymeleaf实现web项 ...

  5. apache目录 vscode_VsCode搭建Java开发环境(Spring Boot项目创建、运行、调试)

    VsCode搭建Java开发环境(Spring Boot项目创建.运行.调试) 安装如下两个主要扩展即可,这两个扩展已关联java项目开发主要使用的maven.springboot等所需要的扩展. 开 ...

  6. VsCode搭建Java开发环境(Spring Boot项目创建、运行、调试)

    本文转载自:https://www.cnblogs.com/miskis/p/9816135.html 安装如下两个主要扩展即可,这两个扩展已关联java项目开发主要使用的maven.springbo ...

  7. 如何安装html启动器,如何在Spring Boot中创建自己的启动器?

    如何在Spring Boot中创建自己的启动器? 也许你有一个内部库包或一个在整个应用程序环境中常用的开源库,如果要在多个Spring Boot应用程序中使用它,为它创建一个Spring Boot启动 ...

  8. Spring Boot教程(一)注解配置与EhCache使用

    2019独角兽企业重金招聘Python工程师标准>>> 快速入门 首先,下载样例工程chapter3-2-2.本例通过spring-data-jpa实现了对User用户表的一些操作, ...

  9. Spring Boot Profile使用详解及配置源码解析

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 二师兄 来源 | 程序新视界 在实践的过程中我 ...

最新文章

  1. 注意!你的 Navicat 可能被投毒了...
  2. 微生物组——宏基因组分析专题培训开课啦!!!
  3. UDP千兆以太网FPGA_verilog实现(五、以太网帧的结构)
  4. AIR720串口2收发数据问题
  5. 【机器视觉】 Halcon批量加载图像
  6. NDVI等植被相关指数
  7. springboot 监听所有异常_SpringBoot——目前Java开发最流行的框架(一)
  8. Ghost in IE6.web标准网页IE6中的幽灵。
  9. HDFS小文件问题解决方案
  10. Win7matlab7.0安装教程,Win7下MATLAB7.0安装教程
  11. 阿里系盒子英菲克i6八核 科学使用 笔记 (2015年12月26日成功)
  12. [规划酱@国土空间] ArcGIS工具| 三调转换之新用地用海分类
  13. 喻文强的加入购物车效果(完整版,仅供参考)
  14. [poj3130][半平面交]How I Mathematician Wonder What You Are!
  15. 网站并发量的计算方法
  16. DP的一些杂题(思维型)
  17. Fedora最新下载地址
  18. Java对接海康摄像头坑点总结
  19. 人工智能基础之数学符号篇
  20. 微信支付与微信转账的区别

热门文章

  1. Vue中使用v-for实现一对多数据的2层和3层嵌套循环
  2. C#中巧用Lambda表达式实现对象list进行截取
  3. Ubuntu Server 16.04 LTS上使用Docker部署Tomcat
  4. Python3中提示:no module named 'wxpy'
  5. 用Tkinter的Cancas实现一个写字板
  6. 说说TDD的好处和坏处-对话
  7. flutter的安装与设置
  8. 项目管理过程中的一些注意事项
  9. linux系统下载经验,linux系统的学习经验首篇
  10. java与jquery的选择器区别_JQuery选择器