1. 简介

通过了解SpringBoot的原理后,我们可以手撸一个spring-boot-starter来加深理解。

1.1 什么是starter

spring官网解释

  • starters是一组方便的依赖描述符(根据功能特点将用到的依赖标记封装到同一个pom中),可以将其包含在应用程序中。
  • 通过starters可以获取所需的所有Spring和相关技术的一站式服务,而无需搜索示例代码或复制粘贴加载的依赖项描述符。

1.2 命名规则

所有官方首发都遵循类似的命名模式:spring-boot-starter-*,其中*是特定类型的应用程序,例如: spring-boot-starter-web

第三方启动器不应以spring-boot开头,因为它是为官方 Spring Boot 工件保留的,相反çç第三方启动器通常以项目名称开头,例如:ldx.spring-boot-starter

1.3 代码结构

如图,官方的spring-boot-starter Jar中其实没有包含代码,starter其实是就是一组依赖描述的集合,而其中主要包含的就是autoconfigure模块和一些必要的依赖模块。

spring-boot官方所有的auto-configuration-classes

springboot官方的starter中依赖如下:

当我们进入到官方autoconfiguration中查看redis配置源码如下,而我们待会儿也会模仿RedisAutoConfiguration写一个自己的starter

2. 开撸

spring官方学习地址

2.1 项目结构

结构说明:

├── redis-spring-boot-starter  # 自定义的starter模块
│   ├── pom.xml
├── spring-boot-autoconfigure # 自定义的auto configure模块
│   ├── pom.xml
│   └── src
│   └── main
│   ├── java
│   │   └── com
│   │   └── ldx
│   │   └── autoconfigure
│   │   └── config
│   │   ├── RedisAutoConfiguration.java # redis 自动配置类
│   │   └── RedisProperty.java # redis property 参数绑定类
│   └── resources
│   └── META-INF
│   └── spring.factories # spring自动装配配置文件
└── test # 功能测试模块
├── pom.xml
├── src
│   └── main
│   ├── java
│   │   └── com
│   │   └── ldx
│   │   └── test
│   │   └── TestApplication.java # 启动类
│   └── resources
│   └── application.yaml # 资源文件

2.2 spring-boot-autoconfigure

正如简介中提到的一样,该模块用于提供autoconfigure核心功能,通过META-INF/spring.factories实现对RedisAutoConfiguration.class的扫描,然后在RedisAutoConfiguration.class中实现Jedis的条件化注入,从而实现springboot的自动装配功能。

2.2.1 导入依赖

spring-boot-autoconfigure-processor是一个注释处理器,依赖用于生成META-INF/spring-autoconfigure-metadata.properties并且被包含在项目 jar 中,其文件记录了当前classpath下所有的autoconfigure的元信息,在项目启动时会先扫描此文件(如果存在),此文件有助于缩短启动时间,但不是程序正常运行所必需的。

<?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.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ldx</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-autoconfigure</name>
<description>自定义的 spring-boot-autoconfigure</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--引入redis客户端 jedis依赖-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<!-- 防止当前依赖被传递引用 -->
<optional>true</optional>
</dependency>
<!--自动配置注解注释处理器,
用于生成META-INF/spring-autoconfigure-metadata.properties包含在项目中-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

2.2.2 RedisProperty

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties; /**
* redis 属性注入类
*
* @author ludangxin
* @date 2021/8/1
*/
@Data
// 用于读取配置文件中的链接信息
@ConfigurationProperties(prefix = "redis")
public class RedisProperty {
private String host = "localhost"; private int port = 6379;
}

2.2.3 RedisAutoConfiguration

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import redis.clients.jedis.Jedis; /**
* redis 自动化配置类
*
* @author ludangxin
* @date 2021/8/1
*/
@ConditionalOnClass(Jedis.class)
@EnableConfigurationProperties(RedisProperty.class)
public class RedisAutoConfiguration { @Bean
@ConditionalOnMissingBean(Jedis.class)
public Jedis jedis(RedisProperty redisProperty) {
return new Jedis(redisProperty.getHost(), redisProperty.getPort());
}
}

2.2.4 spring.factories

resources下创建META-INF/spring.factoriesEnableAutoConfiguration指向RedisAutoConfiguration

org.springframework.boot.autoconfigure.EnableAutoConfiguration = \
com.ldx.autoconfigure.config.RedisAutoConfiguration

2.2.5 安装依赖

将当前模块打成Jar安装到本地仓库。

2.3 redis-spring-boot-starter

2.3.1 导入依赖

在其pom中添加我们刚才创建的spring-boot-autoconfigure模块,并且添加jedis模块(autoconfigure模块中jedis不允许传递依赖因为将来autoconfigure文件中的会有各种各样的第三方自动化配置,不可能全部传递依赖,只能是用到哪个的时候就自行在starter中添加哪个即可)

<?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.0</modelVersion>
<groupId>com.ldx</groupId>
<artifactId>redis-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>redis-spring-boot-starter</name>
<description>customize starter</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--引用自己创建的spring-boot-autoconfigure model-->
<dependency>
<groupId>com.ldx</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 引用jedis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.3</version>
</dependency>
</dependencies>
</project>

2.3.2 安装依赖

将当前模块打成Jar安装到本地仓库。

2.4 test

test模块为测试模块,测试starter功能。

2.4.1 导入依赖

<?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.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ldx</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>test</name>
<description>测试springboot-starter</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 引用自己创建的redis-starter -->
<dependency>
<groupId>com.ldx</groupId>
<artifactId>redis-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

2.4.2 修改启动类

package com.ldx.test;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import redis.clients.jedis.Jedis; @Slf4j
@SpringBootApplication
public class TestApplication { public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(TestApplication.class, args);
// 获取jedis bean
Jedis jedis = applicationContext.getBean(Jedis.class);
// add
jedis.set("name", "张三");
log.info(jedis.get("name"));
} }

2.4.3 启动测试

启动项目成功获取到了设置的数据。

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.3) 2021-08-03 23:08:44.531 INFO 13930 --- [ main] com.ldx.test.TestApplication : Starting TestApplication using Java 1.8.0_261 on ludangxindeMacBook-Pro.local with PID 13930 (/Users/ludangxin/workspace/idea/redis-starter/test/target/classes started by ludangxin in /Users/ludangxin/workspace/idea/redis-starter)
2021-08-03 23:08:44.532 INFO 13930 --- [ main] com.ldx.test.TestApplication : No active profile set, falling back to default profiles: default
2021-08-03 23:08:45.062 INFO 13930 --- [ main] com.ldx.test.TestApplication : Started TestApplication in 0.901 seconds (JVM running for 1.384)
2021-08-03 23:08:45.072 INFO 13930 --- [ main] com.ldx.test.TestApplication : 张三

这时我们在test模块的application.yaml文配置redis.port=123测试autoconfigure模块能不能正常的获取配置信息。

启动项目报错如下:

说明配置类正确的获取到了错误的配置信息,符合预期,打完收工。

这时我们再回头看下spring-boot-autoconfigure-processor依赖生产的元信息文件如下:

3. 小结

spring-boot-starter的出现,大大的提升了我们项目的搭建速度和质量(我们仅需导入依赖坐标,然后在配置文件中进行简单的配置即可。再也不用因为依赖找不全,版本对不上,依赖冲突...而烦恼了),并且官方和第三方的starter简化了我们对中间操作(提供了通用的template,整合了对数据库比如jpa或者amqp等操作接口),简直不要太爽。

当我们学习了如何创建自己的starter后,也可以封装我们自己的starter用于项目的建设和使用。

SpringBoot内置Starter

官方地址介绍地址 github源码地址

名称 描述
spring-boot-starter 核心启动器,包括自动配置支持、日志记录和 YAML
spring-boot-starter-activemq 使用 Apache ActiveMQ 的 JMS 消息传递入门
spring-boot-starter-amqp 使用 Spring AMQP 和 Rabbit MQ 的入门者
spring-boot-starter-aop 使用 Spring AOP 和 AspectJ 进行面向方面编程的入门者
spring-boot-starter-artemis 使用 Apache Artemis 进行 JMS 消息传递的入门者
spring-boot-starter-batch 使用 Spring Batch 的启动器
spring-boot-starter-cache 使用 Spring Framework 的缓存支持的 Starter
spring-boot-starter-data-cassandra Starter 使用 Cassandra 分布式数据库和 Spring Data Cassandra
spring-boot-starter-data-cassandra-reactive Starter 使用 Cassandra 分布式数据库和 Spring Data Cassandra Reactive
spring-boot-starter-data-couchbase 使用 Couchbase 面向文档的数据库和 Spring Data Couchbase 的入门者
spring-boot-starter-data-couchbase-reactive Starter 使用 Couchbase 面向文档的数据库和 Spring Data Couchbase Reactive
spring-boot-starter-data-elasticsearch 使用 Elasticsearch 搜索和分析引擎以及 Spring Data Elasticsearch 的入门者
spring-boot-starter-data-jdbc 使用 Spring Data JDBC 的入门者
spring-boot-starter-data-jpa 将 Spring Data JPA 与 Hibernate 结合使用的入门者
spring-boot-starter-data-ldap 使用 Spring Data LDAP 的入门者
spring-boot-starter-data-mongodb 使用 MongoDB 面向文档的数据库和 Spring Data MongoDB 的入门者
spring-boot-starter-data-mongodb-reactive Starter 使用 MongoDB 面向文档的数据库和 Spring Data MongoDB Reactive
spring-boot-starter-data-neo4j 使用 Neo4j 图形数据库和 Spring Data Neo4j 的入门者
spring-boot-starter-data-r2dbc 使用 Spring Data R2DBC 的启动器
spring-boot-starter-data-redis 将 Redis 键值数据存储与 Spring Data Redis 和 Lettuce 客户端一起使用的入门者
spring-boot-starter-data-redis-reactive 将 Redis 键值数据存储与 Spring Data Redis 反应式和 Lettuce 客户端一起使用的入门者
spring-boot-starter-data-rest 使用 Spring Data REST 在 REST 上公开 Spring Data 存储库的启动器
spring-boot-starter-freemarker 使用 FreeMarker 视图构建 MVC Web 应用程序的入门者
spring-boot-starter-groovy-templates 使用 Groovy 模板视图构建 MVC Web 应用程序的入门者
spring-boot-starter-hateoas 使用 Spring MVC 和 Spring HATEOAS 构建基于超媒体的 RESTful Web 应用程序的入门者
spring-boot-starter-integration 使用 Spring Integration 的入门者
spring-boot-starter-jdbc 将 JDBC 与 HikariCP 连接池一起使用的 Starter
spring-boot-starter-jersey 使用 JAX-RS 和 Jersey 构建 RESTful Web 应用程序的初学者。替代方案spring-boot-starter-web
spring-boot-starter-jooq 使用 jOOQ 访问 SQL 数据库的入门者。spring-boot-starter-data-jpa或的替代品spring-boot-starter-jdbc
spring-boot-starter-json 读写json的Starter
spring-boot-starter-jta-atomikos 使用 Atomikos 的 JTA 事务入门
spring-boot-starter-mail 使用 Java Mail 的 Starter 和 Spring Framework 的电子邮件发送支持
spring-boot-starter-mustache 使用 Mustache 视图构建 Web 应用程序的入门者
spring-boot-starter-oauth2-client 使用 Spring Security 的 OAuth2/OpenID Connect 客户端功能的入门者
spring-boot-starter-oauth2-resource-server 使用 Spring Security 的 OAuth2 资源服务器功能的入门者
spring-boot-starter-quartz 使用 Quartz 调度器的启动器
spring-boot-starter-rsocket 用于构建 RSocket 客户端和服务器的 Starter
spring-boot-starter-security 使用 Spring Security 的入门者
spring-boot-starter-test Starter 用于使用包括 JUnit Jupiter、Hamcrest 和 Mockito 在内的库测试 Spring Boot 应用程序
spring-boot-starter-thymeleaf 使用 Thymeleaf 视图构建 MVC Web 应用程序的初学者
spring-boot-starter-validation 将 Java Bean 验证与 Hibernate Validator 结合使用的入门工具
spring-boot-starter-web 使用 Spring MVC 构建 Web(包括 RESTful)应用程序的入门者。使用 Tomcat 作为默认的嵌入式容器
spring-boot-starter-web-services 使用 Spring Web 服务的入门者
spring-boot-starter-webflux 使用 Spring Framework 的 Reactive Web 支持构建 WebFlux 应用程序的 Starter
spring-boot-starter-websocket 使用 Spring Framework 的 WebSocket 支持构建 WebSocket 应用程序的 Starter

除了应用程序启动器之外,以下启动器还可用于添加生产就绪功能:

名称 描述
spring-boot-starter-actuator 使用 Spring Boot 的 Actuator 的 Starter,它提供了生产就绪的特性来帮助你监控和管理你的应用程序

最后,Spring Boot 还包括以下启动器,如果您想排除或交换特定的技术方面,可以使用它们:

名称 描述
spring-boot-starter-jetty 使用 Jetty 作为嵌入式 servlet 容器的启动器。替代方案spring-boot-starter-tomcat
spring-boot-starter-log4j2 使用 Log4j2 进行日志记录的启动器。替代方案spring-boot-starter-logging
spring-boot-starter-logging 使用 Logback 进行日志记录的启动器。默认日志记录启动器
spring-boot-starter-reactor-netty 使用 Reactor Netty 作为嵌入式响应式 HTTP 服务器的启动器。
spring-boot-starter-tomcat 使用 Tomcat 作为嵌入式 servlet 容器的启动器。使用的默认 servlet 容器启动器spring-boot-starter-web
spring-boot-starter-undertow 使用 Undertow 作为嵌入式 servlet 容器的启动器。替代方案spring-boot-starter-tomcat

手撸一个SpringBoot-Starter的更多相关文章

  1. 手撸一个SpringBoot的Starter,简单易上手

    前言:今天介绍一SpringBoot的Starter,并手写一个自己的Starter,在SpringBoot项目中,有各种的Starter提供给开发者使用,Starter则提供各种API,这样使开发S ...

  2. 手写一个springboot starter

    springboot的starter的作用就是自动装配.将配置类自动装配好放入ioc容器里.作为一个组件,提供给springboot的程序使用. 今天手写一个starter.功能很简单,调用start ...

  3. 从头带你撸一个Springboot Starter

    我们知道 SpringBoot 提供了很多的 Starter 用于引用各种封装好的功能: 名称 功能 spring-boot-starter-web 支持 Web 开发,包括 Tomcat 和 spr ...

  4. 看了 Spring 官网脚手架真香,也撸一个 SpringBoot DDD 微服务的脚手架!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 为什么我们要去造轮子? 造轮子的核心目的,是为了解决通用共性问题的凝练和复用. 虽然 ...

  5. 手撸一个springsecurity,了解一下security原理

    手撸一个springsecurity,了解一下security原理 转载自:www.javaman.cn 手撸一个springsecurity,了解一下security原理 今天手撸一个简易版本的sp ...

  6. 使用Java Socket手撸一个http服务器

    原文连接:使用Java Socket手撸一个http服务器 作为一个java后端,提供http服务可以说是基本技能之一了,但是你真的了解http协议么?你知道知道如何手撸一个http服务器么?tomc ...

  7. 【手撸一个ORM】MyOrm的使用说明

    [手撸一个ORM]第一步.约定和实体描述 [手撸一个ORM]第二步.封装实体描述和实体属性描述 [手撸一个ORM]第三步.SQL语句构造器和SqlParameter封装 [手撸一个ORM]第四步.Ex ...

  8. 第二篇-用Flutter手撸一个抖音国内版,看看有多炫

    前言 继上一篇使用Flutter开发的抖音国际版 后再次撸一个国内版抖音,大部分功能已完成,主要是Flutter开发APP速度很爽,  先看下图 项目主要结构介绍 这次主要的改动在api.dart 及 ...

  9. 通过 Netty、ZooKeeper 手撸一个 RPC 服务

    说明 项目链接 微服务框架都包括什么? 如何实现 RPC 远程调用? 开源 RPC 框架 限定语言 跨语言 RPC 框架 本地 Docker 搭建 ZooKeeper 下载镜像 启动容器 查看容器日志 ...

随机推荐

  1. Unity 添加,修改默认创建脚本模板

    Unity 默认创建的脚本可以添加也可以修改,不需要修改Editor. 一.找到模板目录 \Editor\Data\Resources\ScriptTemplates 二.如果要修改模板,直接打开修改 ...

  2. 解决CentOS下service 功能 不能使用 bash: service: command not found

    首先检查自己是否 使用的是root用户 在centos系统中,如果/sbin目录下没有service这个命令,就会出现 bash: service: command not found 解决步骤如下: ...

  3. 99、centos下安装teamviewer

    99.1.teamviewer简介: TeamViewer是一个能在任何防火墙和NAT代理的后台用于远程控制的应用程序,桌面共享和文件传输的简单且快速的解决方案. 为了连接到另一台计算机,只需要在两台 ...

  4. Camunda工作流引擎简单入门

    官网:https://camunda.com/ 官方文档:https://docs.camunda.org/get-started/spring-boot/project-setup/ 阅读新体验:h ...

  5. Reactive Spring实战 -- 响应式MySql交互

    本文与大家探讨Spring中如何实现MySql响应式交互. Spring Data R2DBC项目是Spring提供的数据库响应式编程框架. R2DBC是Reactive Relational Dat ...

  6. php混淆加密解密实战

    在查看别人的php源码的时候,我们经常会看到加密后的php代码.那么php加密原理是什么呢?怎么解密呢? 混淆加密 我们从百度随便搜索一个加密网站,例如:http://dezend.qiling.or ...

  7. linux学习之路第三天(vim和vi使用)

    vi和vim编辑器 vi和vim的三种常见模式 1.正常模式 在正常模式下,我们可以使用快捷键 以vim打开一个档案就直接进入一般模式了(这是默认的模式).在这个模式中,你可以使用 上下左右按键来移动 ...

  8. linux学习之路第五天(文件目录类第一部分)

    文件目录类 pwd 指令 基本语法 pwd (显示当前目录的绝对路径) Ls 指令 cd 指令 -代表的是上一级目录 mkdir指令 用于创建目录 基本语法 mkdir [选项] 要创建的目录 常用选 ...

  9. IDA 动态调试

    感谢南邮,让我把ida动态调试,给搞定了,困扰了很久,之前下的ubuntu的源,好像有问题,ifconfig这个命令一直装不上,突然想起来了我的服务器很久没用了,重装了下系统,换成ubuntu,这里记 ...

  10. 官宣.NET 6 预览版4

    我们很高兴发布 .NET 6 Preview 4.我们现在大约完成了 .NET 6 发布的一半.现在是一个很好的时机,可以再次查看.NET6的完整范围.许多功能都接近最终形式,而其他功能将很快推出,因 ...