基础知识
Spring Boot Starter 本质上是一个封装好的依赖模块,方便开发者快速引入所需功能。自定义 Starter 通常包括自动配置类、条件注解、属性配置类,以及 Maven/Gradle 的依赖管理。
核心组件:
- 配置属性类(@ConfigurationProperties):绑定 application.properties 中的自定义配置。
- 自动配置类(@Configuration + 条件注解):通过 @ConditionalOnClass、@ConditionalOnProperty 等实现条件化 Bean 注册。
- 依赖声明(pom.xml):最小化依赖传递,通过 optional=true 控制非必要依赖。
目录结构
我们先看一下待会要创建的 SpringBootStarter 项目文件结构:
(此处展示项目目录结构)
实践构建
Spring Boot Starter 项目创建
首先使用 Maven 创建一个空的 Java 项目 spring-boot-starter-demo,在 pom.xml 中加入 SpringBoot 依赖以及 Starter 规范依赖。
1. Spring Boot Starter Maven 依赖
<dependencies>
<!-- Spring Boot 自动配置核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- Starter 配置元数据处理器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Lombok 依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
此外,为了在之后的 SpringBoot 测试项目引入,pom 文件中必须有这样的信息声明:
<groupId>com.cxytiandi</groupId>
<artifactId>spring-boot-starter-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>SpringBootStarterDemo</name>
<description>自定义 SpringBootStarter 示例</description>
2. 配置属性类
创建一个配置类,用于在属性文件中配置值,绑定 application.properties 中自定义的配置。
package com.cxytiandi.demo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties("spring.user")
public class UserProperties {
private String name;
}
3. 定义 Client
再定义一个 Client,里面定义一个方法,用于获取配置中的值。
package com.cxytiandi.demo;
public class UserClient {
private final UserProperties userProperties;
// 使用 final 增强不可变性
public UserClient(UserProperties userProperties) {
this.userProperties = userProperties;
}
public String getName() {
return userProperties.getName();
}
}
自动创建客户端
上面已经具备了最基本的 Starter 的包,不过现在还不能使用 UserClient,因为还没有它的实例。我们通过编写自动配置类,使用 @Configuration 和 @Conditional 注解实现条件化自动配置,创建实例。
@Bean
@ConditionalOnProperty(prefix = "spring.user", name = "enabled", havingValue = "true")
public UserClient userClient(UserProperties userProperties) {
return new UserClient(userProperties);
}
Spring Boot 通过 SPI(Service Provider Interface)识别自动配置类。Spring Boot 会默认扫描跟启动类平级的包,假如我们的 Starter 跟启动类不在同一个主包下,如何能让 UserAutoConfigure 生效?在 resources 下创建一个 META-INF 文件夹,然后在 META-INF 文件夹中创建一个 spring.factories 文件,文件中指定自动配置的类:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.cxytiandi.demo.UserAutoConfigure
编写元数据 (可选)
生成配置提示信息,方便开发者在 IDE 中使用。 路径:src/main/resources/META-INF/spring-configuration-metadata.json
{
"groups": [
{
"name": "spring.user",
"type": "com.cxytiandi.demo.UserProperties",
"sourceType": "com.cxytiandi.demo.UserProperties"
}
],
"properties": [
{
"name": "spring.user.name",
"type": "java.lang.String",
"description": "用户名称配置,用于标识当前用户",
"defaultValue": null
}
]
}
Starter 安装到本地仓库
当我们在 Starter 项目中执行 mvn install 命令时,Maven 会编译代码并打包成 JAR 文件,同时将 JAR 文件、POM 文件等元数据存入本地仓库,路径为:
~/.m2/repository/com/cxytiandi/spring-boot-starter-demo/1.0.0-SNAPSHOT/
其中包含 spring-boot-starter-demo-1.0.0-SNAPSHOT.jar 和 spring-boot-starter-demo-1.0.0-SNAPSHOT.pom。本地开发时,只要 Starter 已通过 mvn install 安装到本地仓库,测试项目就能直接引用。接下来我们进行一下测试自定义的 Starter。
测试 Starter
新建一个 SpringBoot 项目,在 pom.xml 添加本地 Starter 依赖。
1. SpringBootStarter 使用 Maven 配置
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.cxytiandi</groupId>
<artifactId>spring-boot-starter-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
引入之后就直接可以使用 UserClient,UserClient 在项目启动的时候已经自动初始化好。
2. 客户端使用
@RestController
public class UserController {
@Autowired
private UserClient userClient;
@GetMapping("/user/name")
public String getUserName() {
return userClient.getName();
}
}
3. 配置属性文件中启动
spring.user.name=yinjihuan
spring.user.enabled=true
4. 结果
访问 /user/name 就可以返回我们配置的 yinjihuan。
使用注解开启 Starter 自动构建
在之前我们使用的是通过在 resources 下创建一个 META-INF 文件夹的 spring.factories 文件,其实也可以通过注解的方式来开启是否自动配置。如果用注解的方式,那么 spring.factories 就不需要编写了。
注解定义如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({UserAutoConfigure.class})
public @interface EnableUserClient {}
这段代码的核心是 @Import({UserAutoConfigure.class}),通过导入的方式实现把 UserAutoConfigure 实例加入 SpringIOC 容器中,这样就能开启自动配置了。使用方式就是我们在测试项目 SpringBootDemoApplication 中的启动类上加上该注解,就能使用自定义 Starter 了。
@SpringBootApplication
@EnableUserClient
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
打包与发布
当然自定义 Starter 完后,我们可以构建 Jar 包并发布到 Maven 仓库,Maven 仓库分为公共库以及私有库。
1. 构建 Jar 包
使用 Maven 命令打包:
# 清理并编译项目,生成 Jar 包(存放在 target/ 目录)
mvn clean package
# 同时将 Jar 包安装到本地仓库(供本地其他项目依赖)
mvn clean install
2. 发布到 Maven 仓库
如果是公共库,注册到 Maven Central。Maven Central 是全球最大的公共 Maven 仓库,需通过 Sonatype Nexus Repository Manager 提交。
详细步骤:
- 访问 Sonatype Jira 注册页面,创建账号并提交项目申请(需提供 groupId 对应的域名所有权证明,如 com.cxytiandi 需拥有 cxytiandi.com 域名)。
- 生成 GPG 签名
# 安装 GPG 工具(Linux/macOS: gpg, Windows: Gpg4win)
# 生成密钥对
gpg --gen-key
# 导出公钥(提交到 Sonatype 及 Maven Central)
gpg --export -a [email protected] > public.key
- 配置 POM 文件
<project>
<!-- 其他配置 -->
<properties>
<!-- 强制使用 GPG 签名 -->
<gpg.executable>gpg</gpg.executable>
<gpg.passphrase>你的 GPG 密钥密码</gpg.passphrase>
</properties>
<distributionManagement>
<!-- 快照仓库(开发版本) -->
<snapshotRepository>
<id>sonatype-nexus-snapshots</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<!-- 发布仓库(正式版本) -->
<repository>
<id>sonatype-nexus-staging</id>
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<name>Your Name</name>
<email>[email protected]</email>
</developer>
</developers>
</project>
- 执行发布命令
# 发布快照版本(版本号需包含 -SNAPSHOT)
mvn clean deploy -P release-sonatype
# 发布正式版本(需先移除 -SNAPSHOT 后缀)
mvn clean deploy -P release-sonatype -DskipTests
- 在 Maven Central 验证 提交后等待 Sonatype 审核(通常 1-2 小时),审核通过后,运行以下命令同步索引:
mvn versions:update-release-repository
如果是私有库,配置 Nexus/Artifactory 等仓库,并更新 pom.xml 中的发布信息:以 Nexus 为例,假设私有仓库地址为 http://your-nexus-server/repository/maven-releases/。
- 配置仓库信息
<distributionManagement>
<!-- 快照仓库(开发版本,路径包含 snapshots/) -->
<snapshotRepository>
<id>nexus-snapshots</id>
<url>http://your-nexus-server/repository/maven-snapshots/</url>
</snapshotRepository>
<!-- 发布仓库(正式版本,路径包含 releases/) -->
<repository>
<id>nexus-releases</id>
<url>http://your-nexus-server/repository/maven-releases/</url>
</repository>
</distributionManagement>
- 配置认证信息
<servers>
<server>
<id>nexus-snapshots</id>
<!-- 需与 pom.xml 中的 id 一致 -->
<username>仓库用户名</username>
<password>仓库密码</password>
</server>
<server>
<id>nexus-releases</id>
<username>仓库用户名</username>
<password>仓库密码</password>
</server>
</servers>
- 执行发布命令
# 发布快照版本(版本号为 x.x.x-SNAPSHOT)
mvn clean deploy -DaltSnapshotRepository=nexus-snapshots::default::http://your-nexus-server/repository/maven-snapshots/
# 发布正式版本(版本号为 x.x.x)
mvn clean deploy -DaltRepository=nexus-releases::default::http://your-nexus-server/repository/maven-releases/
总结
本期博客从零开始搭建 Spring Boot Starter,学习完后,我们可以更深入理解 Spring Boot Starter 的内部原理,能够更好的理解 SpringBoot 的启动流程以及增加对 SpringBoot 自动配置的理解。


