原文:https://shimo.im/docs/ywxu41XEYxYXYy3U/read

如果我们系统中想要拥有自动配置的功能,可以自己编写一个starter (启动器),想想就觉得很酷,因为这意味着我们不仅有自己定义的自动配的功能,而且具有更通用的耦合度更低的配置。

以一个简单功能为例:浏览器发送 sayHello 请求,服务器接受请求并处理,响应 Hello 。

首先我们看下工程结构:

helloworld-spring-boot-starter-autoconfigure(以下简称autoconfigure):该模块用来实现 Helloworld 的自动配置功能,它的打包方式为 jar;

helloworld-spring-boot-starter(以下简称starter):该模块的打包方式是 jar,依赖 autoconfigure 模块,它不写任何代码,只做自动配置包的自动引入,如果要使用 helloworld 自动配置功能,只要在 pom 文件中引入 starter 模块即可:

<dependency><groupId>com.seagetech.spring.boot</groupId><artifactId>helloworld-spring-boot-starter</artifactId><version>0.0.1-SNAPSHOT</version>
</dependency>

1 项目工程的创建

1.1 创建Empty Project

1) 新建一个空的项目,如下图,点击Next

2) 输入项目名称以及选择项目存放路径,点击Finish

1.2 创建starter模块

1) 在1.1节中新建的空项目基础上新建一个Module

2) 选择Maven,点击Next

3) 输入GroupId、ArtifactId 和 Version 信息,点击Finish

4) 由于这个模块只做自动配置包的引入,所有删除 src 下的包,最终项目结构如下:

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.0</modelVersion><groupId>com.seagetech.spring.boot</groupId><artifactId>helloworld-spring-boot-starter</artifactId><version>1.0-SNAPSHOT</version>
</project>

1.3 创建 autoconfigure 模块

1) 按1.2节第1步,新建一个 Module,并选择 Spring Initializr,点击Next

2) 输入项目相关信息,如下图所示:

3) 选择依赖,我们这里只选择web场景的依赖,点击Next

4) 默认,不需要改动,点击Finish

5) 删除 SpringBoot 自动创建的主配置类、resources 下所有文件(夹)以及 test 文件夹,最终项目结构如下:

pom.xml(已删除 test 测试模块的自动配置包以及 build 下的 Maven 插件)

<?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.0</modelVersion>
<groupId>com.seagetech.spring.boot</groupId>
<artifactId>helloworld-spring-boot-starter-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>helloworld-spring-boot-starter-autoconfigure</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>

6) 在1.2节创建的 helloworld-spring-boot-starter 的 pom 下模块引入本节创建的 autoconfigure 模块:

<dependency>
<groupId>com.seagetech.spring.boot</groupId>
<artifactId>helloworld-spring-boot-starter-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

1.4 实现HelloWorld自动配置

1) 在 helloworld 包下新建 HelloWorldProperties 类,作为配置类,目的是后面使用这个自动配置,直接可以在 application.properties 文件中配置:

package com.seagetech.spring.boot.helloworld;import org.springframework.boot.context.properties.ConfigurationProperties;/**
* HelloWorld属性配置类
* @auther: wangzb
* @date: 2018/11/13 22:21
*/
@ConfigurationProperties(prefix = "hello")
public class HelloWorldProperties {/*** 打招呼的内容,默认为“World!”*/private String msg = "World!";public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}}

2) 新建 HelloWorldService 接口,并实现:

接口:

/**
* @auther: wangzb
* @date: 2018/11/13 22:28
*/
public interface HelloWorldService {/*** 打招呼方法* @param name 人名,向谁打招呼使用* @return*/String sayHello(String name);}

实现类:

/**
* @auther: wangzb
* @date: 2018/11/13 22:33
*/
@Component
public class HelloWorldServiceImpl implements HelloWorldService{@Autowiredprivate HelloWorldProperties helloWorldProperties;/*** 打招呼方法** @param name 人名,向谁打招呼使用* @return*/@Overridepublic String sayHello(String name) {return "Hello " + name + " " + helloWorldProperties.getMsg();}}

3) 新建 HelloWorldAutoConfiguration 配置类

/**
* @auther: wangzb
* @date: 2018/11/13 22:37
*/
@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties({HelloWorldProperties.class})
@Import(HelloWorldServiceImpl.class)
public class HelloWorldAutoConfiguration {}

1.5 创建 spring.factories 文件

在 SpringBoot自动配置原理 中,我们提到 @EnableAutoConfiguration 的关键功能是使用 SpringFactoriesLoader.loadFactoryNames 方法来扫描具有 META-INF/spring.factories 文件的 jar 包,这样我们的自动配置类才能生效,所以我们在 autoconfigure 模块的 resources 下创建 META-INF/spring.factories 文件:

在 spring.factories 中写入:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.seagetech.spring.boot.helloworld.HelloWorldAutoConfiguration

2. helloworld 自动配置的使用

创建好 helloworld 自动配置项目后,接下来就是使用了,我们在 Idea 中使用 install 将1节中创建好的 starter/autoconfigure 模块打包到本地 Maven 创库,然后在 SpringBoot入门 章节创建的 sping-boot-demo 项目中使用,在其 pom 文件中引入:

<dependency><groupId>com.seagetech.spring.boot</groupId><artifactId>helloworld-spring-boot-starter</artifactId><version>0.0.1-SNAPSHOT</version>
</dependency>

在主配置类路径下创建 HelloWorldController :

package com.seagetech.springbootdemo;import com.seagetech.spring.boot.helloworld.HelloWorldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;/**
* @auther: wangzb
* @date: 2018/11/17 11:17
*/
@Controller
public class HelloWorldController {@Autowiredprivate HelloWorldService helloWorldService;@RequestMapping(value = "/sayHello")public String sayHello(String name){return helloWorldService.sayHello(name);}}

启动项目,在浏览器输入:http://localhost:8080/sayHello?name=wangzb,浏览器返回:

我们在重启项目,重复以上步骤,浏览器响应:

3. 元数据的配置

到目前为止,helloworld 的自动配置功能已实现,并且正确使用了,但还有一点不够完美,如果你也按上面步骤实现了自己的 helloworld 自动配置,在 application.properties 中配置 hello.msg 属性时,你会发现并没有提示你有关该配置的信息,但是如果你想配置 Tomcat 端口时,输入 server.port 是有提示的:

这种功能我们如何做呢,我们打开 SpringBoot入门 章节下载的 “spring-boot-reference.pdf” 文件,在目录中找到 “Appendix B. Configuration Metadata(附录B.配置元数据)”,下面我们使用谷歌来翻译下相关原文:

Spring Boot jars include metadata files that provide details of all supported configuration properties.The files are designed to let IDE developers offer contextual help and “code completion” as users are working with application.properties or application.yml files.

Spring Boot jar 包含元数据文件,提供所有支持的配置属性的详细信息。这些文件旨在让 IDE 开发人员使用 application.properties或 application.yml 文件像用户一样提供上下文帮助和“代码完成”

……

B.1 Metadata Format

Configuration metadata files are located inside jars under META-INF/spring-configurationmetadata.json They use a simple JSON format with items categorized under either “groups” or “properties” and additional values hints categorized under “hints”, as shown in the following example:

B.1 元数据格式

配置元数据文件位于 META-INF / spring-configuration-metadata.json下的 jar 中。它们使用简单的 JSON 格式,其中的项目分类为 “groups” 或 “properties” 和其他值提示分类在 “hints” 下。

….

看看它的例子:

{"groups": [{
"name": "server",
"type": "org.springframework.boot.autoconfigure.web.ServerProperties",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
},
...
],
"properties": [{
"name": "server.port",
"type": "java.lang.Integer",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
},{
"name": "server.address",
"type": "java.net.InetAddress",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
},
...
],
"hints": [{
"name": "spring.jpa.hibernate.ddl-auto",
"values": [{
"value": "none",
"description": "Disable DDL handling."
},{
"value": "validate",
"description": "Validate the schema, make no changes to the database."
},{
"value": "update",
"description": "Update the schema if necessary."
}]
]}

所以元数据是在位于 META-INF/spring-configuration-metadata.json 下配置的,下面就列出有关 groups、properties、hints 使用。

3.1 Group属性

“groups” 中包含的 JSON 对象可以包含下表中显示的属性:

3.2 Property属性

properties 数组中包含的 JSON 对象可由以下属性构成:

3.3 hints属性

hints 数组中包含的 JSON 对象可以包含以下属性:

每个 “hints” 元素的 values 属性中包含的 JSON 对象可以包含下表中描述的属性:

每个 “hints” 元素的 providers 属性中的 JSON 对象可以包含下表中描述的属性:

3.4 配置元数据

所以如果想有更好的用户体验,可以为我们自定义的 starter 配置元数据,下面就为 HelloWorld 配置元数据。

在 META-INF 下创建 spring-configuration-metadata.json 文件:

在文件中输入如下内容:

{
"hints":[{
"name":"hello.msg",
"values":[{
"value":"你好",
"description":"中文方式打招呼"
},{
"value":"Hi",
"description":"英文方式打招呼"
}]
}],
"groups":[
{
"sourceType": "com.seagetech.spring.boot.helloworld.HelloWorldProperties",
"name": "hello",
"type": "com.seagetech.spring.boot.helloworld.HelloWorldProperties"
}],
"properties":[
{
"sourceType": "com.seagetech.spring.boot.helloworld.HelloWorldProperties",
"name": "hello.msg",
"type": "java.lang.String",
"description": "打招呼的内容",
"defaultValue": "Worlds"
}]
}

然后将 autoconfigure 模块重新打包,接下来就是在 spring-boot-demo 项目中使用,如下图所示,就有了属性的提示:

Spring Boot 如何自定义Starter,你知道吗?相关推荐

  1. Spring Boot:自定义starter

    来源:阿杜的世界 号外:最近整理了一下以前编写的一系列Spring Boot内容,整了个<Spring Boot基础教程>的PDF,关注我,回复:001,快来领取吧-!更多内容持续整理中, ...

  2. Spring Boot 2.X - Spring Boot整合Swagger2(starter方式)

    文章目录 Spring Boot 2.X - Spring Boot整合Swagger2(starter方式) 引入依赖 添加@EnableSwagger2Doc注解 创建实体类 创建Controll ...

  3. Spring Boot的启动器Starter详解

    Spring Boot的启动器Starter详解 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs Spring Boot ...

  4. spring boot之自定义的注解的切面编程

    springBoot目录 1. 前言 在上一章中我们知道了,注解的本质其实就是一个标签.但是我们可以通过反射或其他方式从注解的宿主对象上获取到注解对象信息,这就让注解的可玩性变得很强.可以通过注解来描 ...

  5. springboot跳转html_畅游Spring Boot系列 — 自定义配置

    这里要说的自定义配置主要是两类:一类是关于Spring MVC的扩展配置,一类是Spring Boot自身通过配置文件的自定义配置 首先,我们来看一下SpringBoot中关于Spring MVC的相 ...

  6. 徒手解密 Spring Boot 中的 Starter自动化配置黑魔法

    我们使用 Spring Boot,基本上都是沉醉在它 Stater 的方便之中.Starter 为我们带来了众多的自动化配置,有了这些自动化配置,我们可以不费吹灰之力就能搭建一个生产级开发环境,有的小 ...

  7. Spring Boot简略自定义starters

    更多信息: 本篇算是学习笔记 视频 尚硅谷 配置文件的信息 Spring Boot文档 狂神老师的bilibli账号:如果想学相关的知识可以关注一下 目录 更多信息: Starter 测试安装 Sta ...

  8. spring boot admin 自定义

    自定义通知事件 实现notifier接口 // 此接口在服务端 package de.codecentric.boot.admin.server.notify; public interface No ...

  9. Spring Boot项目自定义启动Banner

    一.什么是banner SpringBoot项目启动的时候会打印一个图案,这个图案就是所说的banner,默认的banner是像下面这个样子, 其实这个图案是可以改变的,可以用自定义的图案. 二.自定 ...

最新文章

  1. 百万奖金悬赏AI垃圾分类,就问你来不来?
  2. Web开发中8个基础常见功能
  3. Zepto Click点透情况解决办法
  4. sklearn自学指南(part59)--神经网络模型(监督)
  5. Hyper-V + CentOS7 网络设置(视频教程)
  6. P1332,nssl1316-血色先锋军【bfs】
  7. numactl:NETLINK示例源码
  8. 【采访】腾讯社交广告高校算法大赛 决赛第一周周冠军——ThreeIdiots比赛经验及心得分享 腾讯广告算法大赛
  9. Java中的泛型全解析(一)
  10. Incorrect username or password (access token)
  11. Sql Server 学习2
  12. python主流测试框架的简介
  13. 分析一个在高并发下的财务支付锁的问题
  14. java中递归遍历文件夹下所有文件
  15. c语言 键盘扫描码 c-free,FreeBarcode条形码制作工具
  16. WEBGIS使用OpenLayers3中Interaction绘制长方形和正方形
  17. 岁末回首,义无反顾!
  18. 莱赞多店管家分析Lazada印尼站点热卖商品,商家运营更轻松
  19. 2020双十一商家物流迎来大考:看拙燕仓如何破局?
  20. 【C语言程序设计】实验 2

热门文章

  1. 斯坦福大学UFLDL教程列表
  2. 乱入Linux界的我是如何学习的
  3. 实现基于渠道和buildType(debug,release)的打包
  4. jQuery 遍历|祖先
  5. mysql批量插入:语法
  6. 关于MySql数据库设计表与查询耗时分析
  7. android ImageButton显示本地图片
  8. IIS7下 301重定向 添加WWW
  9. C/C++语言可变参数表深层探索
  10. java 向下转型_Java_向下转型