前言

在使用SpringBoot框架时,SpringBoot 最强大的功能就是把我们常用的场景抽取封装成了一个个starter,将其称之为场景启动器。搭建项目时,通过引入SpringBoot为我提供的这些不同场景启动器,然后开发者再进行一些属性配置,便能够快速的开发出一个Java Web应用。究其原理,完全归结于SpringBoot封装的这些Starter为我们带来了众多的自动化配置,有了这些自动化配置,使得开发Java项目非常容易且节省了不少成本,出于对这些starter的好奇,于是亲自手把手自定义一个starter,只要你有SSM框架相关知识的基础,那么很容易实现这些自定义场景启动器。

Springboot官方文档关于starters的介绍: https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/html/using-spring-boot.html#using-boot-starter

一、核心知识点

1.1 Starter的机制

SpringBoot中提供的starter是一种非常重要的机制,他抛弃了以前繁杂的配置,将其统一集成进一个个starter启动器,开发者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。starter让我们摆脱了各种依赖库的处理,版本之间的兼容,需要配置各种配置信息的困扰。

SpringBoot会自动通过classpath路径下的类发现需要的Bean,并注册进IOC容器。SpringBoot提供了针对日常企业应用研发各种场景的spring-boot-starter依赖模块。所有这些依赖模块都遵循着约定成俗的默认配置,并允许我们调整这些配置,即遵循“约定大于配置”的理念。

1.2 为什么要自定义starter

默认情况下,SpringBoot官方为我们提供的starter完全足够应对日常开发工作,在了解了SpringBoot封装starter的原理之后,我们或许能思考到,日常开发中,经常会有一些独立于业务之外的配置模块,尤其是在Spring Cloud微服务架构中,一些复用性较高的配置类通常会被拷贝到不同的服务模块下,其实这些配置类代码一模一样,只是某个子服务需要用到,这样很冗余而且很麻烦。

此时,我们便可以将这些可独立于业务代码之外的功能配置模块封装成一个个starter,复用的时候只需要将其在pom中引用starter依赖即可,SpringBoot为我们完成自动装配,这样一来简直不要太爽。

1.3 自定义starter案例

  • 动态数据源切换

  • AOP切面日志拦截处理

  • 主从库读写分离数据源

  • Swagger接口文档配置

    。。。。。。。。等等场景

1.4 自定义starter的命名规则

官方命名规则

  • 前缀:spring-boot-starter-{name}
  • 模式:spring-boot-starter-模块名
  • 举例:spring-boot-starter-web、spring-boot-starter-thymeleaf

自定义命名规则

  • 后缀:{name}-spring-boot-starter
  • 模式:模块-spring-boot-starter
  • 举例:mybatis-spring-boot-starter

二、如何自定义starter

1.如何编写自动配置

想要自定义我们自己的starter,必然要先了解SpringBoot提供的自动配置,以常见的自动配置类WebMvcAutoConfiguration为例,学习一下编写自动配置类需要哪些步骤和注解。

摘自部分源码如下(示例):

@Configuration(proxyBeanMethods = false)@ConditionalOnWebApplication(type = Type.SERVLET)@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,  ValidationAutoConfiguration.class })public class WebMvcAutoConfiguration {

 public static final String DEFAULT_PREFIX = "";

 public static final String DEFAULT_SUFFIX = "";

 private static final String[] SERVLET_LOCATIONS = { "/" };

 @Bean @ConditionalOnMissingBean(HiddenHttpMethodFilter.class) @ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false) public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {  return new OrderedHiddenHttpMethodFilter(); }

 @Bean @ConditionalOnMissingBean(FormContentFilter.class) @ConditionalOnProperty(prefix = "spring.mvc.formcontent.filter", name = "enabled", matchIfMissing = true) public OrderedFormContentFilter formContentFilter() {  return new OrderedFormContentFilter(); }

在这个自动配置类当中,我们需要以下这些注解:对于上述注解,解释如下:

@Configuration  //指定这个类是一个配置类@ConditionalOnXXX  //在指定条件成立的情况下自动配置类才生效@AutoConfigureOrder //指定自动配置类的优先级@AutoConfigureAfter  //指定自动配置类的顺序@Bean  //给容器中添加组件

@ConfigurationPropertie //将application.properties文件中前缀为xx的属性来绑定映射到这个xxxProperties.java类对应的属性上@EnableConfigurationProperties //让标注了@ConfigurationProperties(prefix = "xx")的配置类生效。

2. 如何让配置类加载生效

自动配置类要能加载生效,需要将启动就加载的自动配置类配置在配置在META‐INF/spring.factories中,在resources 下创建文件夹 META-INF 并在 META-INF 下创建文件 spring.factories。例如spring-boot-autoconfigure的spring.factories:

在这里插入图片描述

3. 封装自定义starter模式

在SpringBoot定义的starter中,每一个的启动器starter只用来做依赖导入提供给外部项目需要时导入使用,而启动器starter又依赖于一个自动配置,因此专门来写一个自动配置模块给启动器starter依赖。

3.1 自定义Starter

  • 启动器只用来做依赖导入

  • 专门来写一个自动配置模块;

  • 启动器依赖自动配置模块,项目中引入相应的starter就会引入启动器的所有传递依赖


三. 定义自动配置类模块


1. pom.xml

<?xml  version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0modelVersion>

    <groupId>cn.wechat.bootgroupId>    <artifactId>wechat-spring-boot-autoconfigureartifactId>    <version>1.0-SNAPSHOTversion>

    <parent>        <groupId>org.springframework.bootgroupId>        <artifactId>spring-boot-starter-parentartifactId>        <version>2.2.1.RELEASEversion>        <relativePath/>    parent>

    <dependencies>

        <dependency>            <groupId>org.springframework.bootgroupId>            <artifactId>spring-boot-starterartifactId>        dependency>

        <dependency>            <groupId>org.springframework.bootgroupId>            <artifactId>spring-boot-configuration-processorartifactId>            <optional>trueoptional>        dependency>

        <dependency>            <groupId>org.projectlombokgroupId>            <artifactId>lombokartifactId>        dependency>    dependencies>

project>

2. 定义配置类绑定属性

配置完成后,我们首先创建一个 WxProperties 类,用来接受 application.properties 中注入的属性值,绑定映射到这个类上。

/** * @desc: * @author: cao_wencao * @date: 2020-08-25 16:04 */@Data@Component@ConfigurationProperties(prefix = "wx.config")public class WxProperties {

    private String isOpen;    private String appid;    private String appsecret;    private String appkey;    private String token;}

3. 业务逻辑类

这个业务逻辑类主要用来调用WxProperties 中的属性,在项目启动后,可以使用@Autowired注入WxDemoService类,调用initLoader方法 测试自动配置是否成功生效。

/** * @desc: * @author: cao_wencao * @date: 2020-08-25 16:17 */@Slf4j@Datapublic class WxDemoService {

    private WxProperties wxProperties;

    public String initLoader(String msg) {        String appId = wxProperties.getAppid();        String appKey = wxProperties.getAppkey();        String sercret = wxProperties.getAppsecret();        String token = wxProperties.getToken();        log.info("\n【应用ID】: {} \n【应用Key】: {} \n【应用秘钥】: {} \n【应用令牌】: {} ",appId,appKey,sercret,token);        return msg + ",开始初始化:"+ appId + appKey+sercret +token;    }}

4. 定义自动配置类

/** *  //prefix为配置文件中的前缀, *  //name为配置的名字 *  //havingValue是与配置的值对比值,当两个值相同返回true,配置类生效. * @desc:  微信自动配置类 * @author: cao_wencao * @date: 2020-08-25 16:13 */@Configuration //表明这是一个配置类//当存在配置文件中以wx.config为前缀的属性,属性名称为is-open,然后它的值为enabled时才会实例化一个类。matchIfMissing 表示缺少这个属性时是否加载,如果为true,没有该property属性也会正常加载,如果为false,没有该property属性则报错,默认值是false。@ConditionalOnProperty(prefix = "wx.config", name = "is-open", havingValue = "enabled",matchIfMissing = false)@ConditionalOnClass(WxDemoService.class)//当前项目下classpath下存在WxDemoService类时配置类生效(类加载器中存在指明的类)@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)@EnableConfigurationProperties(WxProperties.class)//使我们之前配置的 @ConfigurationProperties生效,让配置的属性成功的进入Bean 中。public class WxAutoConfiguration {    @Autowired    private WxProperties properties;

    @Bean    public WxDemoService wxDemoService(){        WxDemoService demoService = new WxDemoService();        demoService.setWxProperties(properties);        return demoService;    }}

关于上述自动配置类,注解解释如下:

  • @Configuration: 表明这是一个配置类。
  • @ConditionalOnProperty(prefix = "wx.config", name = "is-open", havingValue = "enabled",matchIfMissing = false): 当存在配置文件中以wx.config为前缀的属性,属性名称为is-open,然后它的值为enabled时才会实例化一个类。matchIfMissing 表示缺少这个属性时是否加载,如果为true,没有该property属性也会正常加载,如果为false,没有该property属性则报错,默认值是false。
  • @ConditionalOnClass(WxDemoService.class): 当前项目下classpath下存在WxDemoService类时配置类生效(类加载器中存在指明的类)
  • @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET):web应用才生效
  • @EnableConfigurationProperties(WxProperties.class) : 使我们之前配置的 @ConfigurationProperties生效,让配置的属性成功的进入Bean 中。

5. @ConditionalOnProperty注解含义

@ConditionalOnProperty表示是否满足具备某个属性条件的条件注解,用来控制@Configuration的自动配置类是否生效。

@Retention(RetentionPolicy.RUNTIME)@Target({ ElementType.TYPE, ElementType.METHOD })@Documented@Conditional(OnPropertyCondition.class)public @interface ConditionalOnProperty {    //数组,获取对应property名称的值,与name不可同时使用 String[] value() default {};

    //配置属性名称的前缀,比如spring.http.encoding String prefix() default "";

    //数组,配置属性完整名称或部分名称    //可与prefix组合使用,组成完整的配置属性名称,与value不可同时使用 String[] name() default {};

    //可与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置 String havingValue() default "";

    //缺少该配置属性时是否可以加载。如果为true,没有该配置属性时也会正常加载;反之则不会生效 boolean matchIfMissing() default false;}
  • prefix:application.properties配置的前缀
  • name:属性是从application.properties配置文件中读取属性值
  • havingValue:配置读取的属性值跟havingValue做比较,如果一样则返回true;否则返回false。如果返回值为false,则该configuration不生效;为true则生效
  • matchIfMissing = true:表示如果没有在application.properties中设置该属性,不匹配,则默认为条件符合,没有该property属性也会正常加载项目。如果为matchIfMissing = false,则表示当没有该property属性时则启动报错。

例如:

@Configurationpublic class WebConfig {

    @Bean    @ConditionalOnProperty(prefix = "rest", name = "auth-open", havingValue = "true", matchIfMissing = true)    public AuthFilter jwtAuthenticationTokenFilter() {        return new AuthFilter();    }

}

上面代码的意思是: 在application.properties文件中是否设置了rest.auth-open 属性并且设置值为rest.auth-open=true ,如果没有设置rest.auth-open 属性,或者设置了rest.auth-open=false ,我们就会通过matchIfMissing = true忽略掉这个属性,项目正常启动并加载jwt的的配置信息,忽略此属性不计,havingValue = "true"的值会跟rest.auth-open 属性的值做对比。

application.properties 配置如下:

rest.auth-open=true #jwt鉴权机制是否开启(true或者false)

6. 在resources文件夹下创建META-INF/spring.factories

在resources文件夹下创建META-INF/spring.factories ,项目启动时会从该文件中扫描通过类的完整路径读取自动配置类,从而实现SpringBoot的自动配置生效。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\cn.wechat.boot.autoconfigure.config.WxAutoConfiguration

四. 定义starter启动器模块

关于定义 starter,前面也说过,很简单,starter启动器只用来做依赖导入,启动器依赖自动配置模块,项目中引入相应的starter就会引入启动器的所有传递依赖。因此我们只需要新建一个空的maven项目,引入自动配置依赖即可。

1. pom.xml

<?xml  version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0modelVersion>

    <groupId>cn.wechat.bootgroupId>    <artifactId>wechat-spring-boot-starterartifactId>    <version>1.0-SNAPSHOTversion>

    <dependencies>

        <dependency>            <groupId>cn.wechat.bootgroupId>            <artifactId>wechat-spring-boot-autoconfigureartifactId>            <version>1.0-SNAPSHOTversion>        dependency>    dependencies>project>

五. 打包安装到仓库

在前面两步中,自动配置模块和启动器starter模块都定义配置完了,接下来我们只需要创建一个标准的SpringBoot项目,引入启动器starter模块的依赖即可,因为maven依赖具有传递性,引入启动器starter后,自动配置模块的依赖就自动传递依赖过去。此时我们需要将自动配置模块和启动器starter模块打包到本地Maven仓库即可。

  • 自动配置模块打包:

  • starter启动器打包:

六. web项目依赖starter

创建SpringBoot 项目,pom.xml文件引入我们自定义的starter启动器,然后在application.properties配置我们自定义自动配置类中所需要的属性。

1. pom.xml

  <?xml  version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0modelVersion>    <parent>        <groupId>org.springframework.bootgroupId>        <artifactId>spring-boot-starter-parentartifactId>        <version>2.2.1.RELEASEversion>        <relativePath/>     parent>    <groupId>com.thinkingcaogroupId>    <artifactId>springboot-starter-testartifactId>    <version>0.0.1-SNAPSHOTversion>    <name>springboot-starter-testname>    <description>Demo project for Spring Bootdescription>

    <properties>        <java.version>1.8java.version>    properties>

    <dependencies>        <dependency>            <groupId>org.springframework.bootgroupId>            <artifactId>spring-boot-starter-webartifactId>        dependency>

        <dependency>            <groupId>cn.wechat.bootgroupId>            <artifactId>wechat-spring-boot-starterartifactId>            <version>1.0-SNAPSHOTversion>        dependency>    dependencies>

    <build>        <plugins>            <plugin>                <groupId>org.springframework.bootgroupId>                <artifactId>spring-boot-maven-pluginartifactId>            plugin>        plugins>    build>

project>

2. 查看依赖情况

在这里插入图片描述

3. application.properties

wx.config.is-open=enabledwx.config.appid=111111wx.config.appkey=222222wx.config.appsecret=999999wx.config.token=abcdefg

4. 创建Controller

/** * @desc: * @author: cao_wencao * @date: 2020-08-25 16:51 */@RestControllerpublic class DemoController {

    @Autowired    private WxDemoService wxDemoService;

    @RequestMapping("/hello")    public String hello(){        String msg = wxDemoService.initLoader("你好");        return msg;    }}

5. 启动项目访问:http://localhost:8080/hello

浏览器显示如下结果:IDEA控制台日志:

2020-08-26 17:39:17.466  INFO 9108 --- [nio-8080-exec-6] c.w.b.a.service.WxDemoService            : 【应用ID】: 111111 【应用Key】: 222222 【应用秘钥】: 999999 【应用令牌】: abcdefg 

6. 自定义starter依赖关系图



七、源码

1. 参考文档:Springboot官方文档关于starters的介绍

2. 源码:https://github.com/Thinkingcao/SpringBootLearning/tree/master/springboot-custom-starter

八、总结

以上就是今天要讲的内容,本文仅仅简单介绍了如何自定义一个我们自己的starter,并且正确的使用它,而SpringBoot为我们提供了大量的starter能使我们快速的应对日常各种web开发,那么除了SpringBoot官方提供的之外,我们可根据自身项目的场景,指定特定场景的starter启动器。

@configurationproperties注解的使用_徒手使用SpringBoot自定义Starter启动器相关推荐

  1. Spring Boot 自动配置的原理、核心注解以及利用自动配置实现了自定义 Starter 组件

    本章内容 自定义属性快速入门 外化配置 自动配置 自定义创建 Starter 组件 摘录:读书是读完这些文字还要好好用心去想想,写书也一样,做任何事也一样 图 2 第二章目录结构图 第 2 章 Spr ...

  2. SpringBoot自定义Starter(自动配置类)

    前言 SpringBoot其实从诞生以来围绕的核心就是快速构建项目,快速构建的前提是有人帮你做好轮子,开发者只要拿来即用就好了,而造好轮子的人就是SpringBoot的开发者,引入自动配置的形式帮助开 ...

  3. spring boot @value取不到值_看看大厂如何自定义starter,还真想不到

    我自己整理了一套java架构资料,还有大厂面试题,需要私信回复"资料"就好了,无偿分享,希望对你有帮助. 背景 使用过Spring Boot的小伙伴都应该知道,一个Spring B ...

  4. SpringBoot 自定义Starter(阿里云短信、消息推送)

    首先在IDEA中创建SpringBoot项目,引入相关必要依赖,本次以阿里云短信/消息推送为例: <dependency><groupId>com.aliyun</gro ...

  5. SpringBoot自定义start启动器图文教程(详细)

    这里写目录标题 1.SpringBoot启动器原理 2.自定义starter 到这已经完成启动stater启动的配置了 1.SpringBoot启动器原理 我们新建一个空的spring boot项目, ...

  6. SpringBoot 自定义starter 保姆级教程(说明+源码+配置+测试)

    1.说明 命名归约-官方命名: 前缀:spring-boot-starter-xxx(比如:spring-boot-starter-web) 命名归约-自定义命名: xxx-spring-boot-s ...

  7. SpringBoot自定义starter时报错:Problems:dependencies.dependency.version‘ for com.zsm.starter:zsm-spring

    Problems:dependencies.dependency.version' for com.zsm.starter:zsm-spring-boot-starter-autoconfigurej ...

  8. SpringBoot:@ConfigurationProperties注解使用与源码

    文章目录 1.美图 2.概述 2.1 源码 3.猜想 4.@SpringBootApplication 5.@EnableAutoConfiguration 1.美图 2.概述 我们在使用Spring ...

  9. 【SpringBoot】SpringBoot @ConfigurationProperties 注解 用法与加载static静态属性

    @ConfigurationProperties [SpringBoot]SpringBoot @ConfigurationProperties 注解 用法与加载static静态属性 @Configu ...

最新文章

  1. 崛起的Python,真的影响了76万人?
  2. Windows Azure Platform Introduction (6) Windows Azure应用程序运行环境
  3. yolov5改进mark
  4. mac电脑抹掉数据要多久_macbook怎么抹掉所有的数据?
  5. 【初探移动前端开发02】移动设备的页面
  6. 【计算理论】计算复杂性 ( 两个带子的图灵机的时间复杂度 )
  7. WCF服务支持HTTP(get,post)方式请求例子
  8. 触发效果当容器的可见性改变时
  9. Caliburn.Micro学习笔记(五)----协同IResult
  10. 通吃AD和宽带 TP-LINK无线路由猫评测
  11. 金融行业的JAVA软件开发
  12. 动力节点_JDBC学习笔记详解【源代码分析】
  13. day2:牛客网 糖果俱乐部
  14. Cypher查询语言--Neo4j中的SQL(6)
  15. AD域建设管理(二)| python3+ldap3管理AD域实践(批量创建OU、用户、改密码、更新OU与用户)
  16. 抖音1元秒杀活动背后赚钱秘诀是什么? 怎么个玩法?
  17. python Pipelines(管道)
  18. flash中导入音乐和制作按钮
  19. 【头歌】科比投篮预测——可视化与探索性数据分析(一)
  20. 嵌入式软件硬件比例_嵌入式做硬件方向好还是软件方向好?

热门文章

  1. 2017-2018-1 20155227 《信息安全系统设计基础》第四周学习总结
  2. php7慢,php-finfo在7.3和7.2上明显慢
  3. 贪心——买卖股票的最佳时机(Leetcode 122)
  4. PAT乙级(1014 福尔摩斯的约会)
  5. figtree如何编辑进化树_进化树的注释:ggtree
  6. python中用于绘制各种图形的区域称作_Python--matplotlib绘图可视化知识点整理(示例代码)...
  7. GaussDB分布式Stream执行计划详解
  8. 快讯:Oracle 18c 通用版本 18.3 正式发布
  9. Oracle 12c 新特性:SQL Plan Directives与过量的动态采样解析
  10. 【伙伴故事】智慧厨电接入华为云+HarmonyOS,你的未来厨房长这样