在 Spring Boot 生态中,Starter(启动器)是核心价值之一,它帮我们实现了自动配置、依赖管理、开箱即用,无需手动繁琐配置和导入依赖,比如spring-boot-starter-web、spring-boot-starter-redis都是官方提供的经典 Starter。
但实际业务开发中,我们常会封装通用工具(如日志组件、短信服务、数据库通用操作),想让其他项目也能一键引入、自动生效,这就需要自定义 Spring Boot Starter。
Spring Boot 自动配置的核心是 @EnableAutoConfiguration,其工作流程可概括为 3 步:
Spring Boot 启动时,会扫描所有依赖包下的自动配置声明文件;
读取文件中配置的自动配置类;
根据自动配置类上的条件注解,判断是否创建 Bean 并注入 Spring 容器,实现“按需配置、自动生效”。
自定义 Starter 的本质就是
编写自动配置类 → 定义配置属性 → 声明自动配置入口 → 打包供其他项目使用避免与官方冲突
官方 Starter:spring-boot-starter-xxx(如 spring-boot-starter-web)
自定义 Starter:xxx-spring-boot-starter(如本文实战的 string-util-spring-boot-starter)
缺一不可
配置属性类(XXXProperties):绑定配置文件中的自定义参数
业务功能类(XXXService):封装通用业务逻辑 / 工具方法
自动配置类(XXXAutoConfiguration):核心,控制 Bean 的创建和生效条件
自动配置声明文件:兼容新旧版本,让 Spring Boot 扫描到自动配置类
核心依赖必须引入,非核心依赖设置为可选,避免传递依赖冲突,兼容 2.x 和 3.x 版本的依赖配置如下(直接复制使用):
<?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.example</groupId>
<artifactId>string-util-spring-boot-starter</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.13</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>以封装字符串脱敏、大小写转换通用工具为例,开发string-util-spring-boot-starter
自定义 Starter 是普通 Maven 项目,不要添加 Spring Boot 启动类(无需 @SpringBootApplication),仅作为工具包供其他项目依赖。
绑定 application.yml 中的自定义配置,支持用户灵活修改,默认值合理配置
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 字符串工具配置属性类
* 配置前缀:string.util,对应配置文件中的string.util.xxx
*/
@ConfigurationProperties(prefix = "string.util")
public class StringUtilProperties {
// 是否开启工具(默认true,无需配置即可生效)
private boolean enabled = true;
// 脱敏符号(默认*,用户可自定义修改)
private String maskChar = "*";
// getter & setter(必须有,否则无法绑定配置)
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getMaskChar() {
return maskChar;
}
public void setMaskChar(String maskChar) {
this.maskChar = maskChar;
}
}封装通用工具方法,逻辑独立,通过构造注入配置属性
/**
* 字符串工具核心类,封装脱敏、大小写转换等通用方法
*/
public class StringUtilService {
// 注入配置属性中的脱敏符号(通过构造方法注入)
private final String maskChar;
public StringUtilService(String maskChar) {
this.maskChar = maskChar;
}
/**
* 字符串脱敏(保留前1位和后1位,中间用指定符号替换,适配手机号、身份证等场景)
* 示例:13812345678 → 1****8(默认符号)、1####8(自定义符号)
*/
public String mask(String str) {
if (str == null || str.length() <= 2) {
return str; // 长度≤2的字符串不脱敏,避免失真
}
return str.substring(0, 1) + maskChar.repeat(4) + str.substring(str.length() - 1);
}
/**
* 字符串转大写(空值安全,避免空指针)
*/
public String toUpper(String str) {
return str == null ? null : str.toUpperCase();
}
}核心类,控制 Bean 的创建、生效条件
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 自动配置类:控制StringUtilService的创建和生效
*/
@Configuration // 标记为Spring配置类
@ConditionalOnClass(StringUtilService.class) // 类路径存在该类时生效(避免依赖缺失报错)
@EnableConfigurationProperties(StringUtilProperties.class) // 开启配置属性绑定
@ConditionalOnProperty(prefix = "string.util", value = "enabled", matchIfMissing = true)
// 配置文件中string.util.enabled=true生效,缺省也生效(默认开启)
public class StringUtilAutoConfiguration {
/**
* 自动创建StringUtilService Bean,注入Spring容器
* @ConditionalOnMissingBean:用户自定义该Bean时,优先使用用户的实现(支持覆盖)
*/
@Bean
@ConditionalOnMissingBean
public StringUtilService stringUtilService(StringUtilProperties properties) {
// 将配置属性中的脱敏符号注入业务类
return new StringUtilService(properties.getMaskChar());
}
}同时创建新旧两个声明文件,Spring Boot 会自动识别版本并使用对应文件,实现全版本兼容,路径必须严格匹配。
Spring Boot 2.0~2.6
文件路径:src/main/resources/META-INF/spring.factories
文件内容(固定格式,替换为自己的自动配置类全限定名):
# Spring Boot 2.7以前版本自动配置声明(固定key,不可修改)
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.StringUtilAutoConfiguration说明:多个自动配置类用,\换行分隔,本文仅一个,直接填写即可。
Spring Boot 2.7+ / 3.x
文件路径:src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件内容(仅填写自动配置类全限定名):
com.example.StringUtilAutoConfiguration在项目根目录执行 Maven 命令,将 Starter 打包到本地仓库(或私服):
mvn clean install打包成功后,其他 Spring Boot 项目即可通过 Maven 依赖引入,自动生效。
string-util-spring-boot-starter
├── src/main/java
│ └── com.example
│ ├── StringUtilProperties.java # 配置属性类
│ ├── StringUtilService.java # 业务功能类
│ └── StringUtilAutoConfiguration.java # 自动配置类
└── src/main/resources
└── META-INF
├── spring.factories # 旧版声明(2.0~2.6)
└── spring/
└── org.springframework.boot.autoconfigure.AutoConfiguration.imports # 新版声明(2.7+ / 3.x)开箱即用
任何 Spring Boot 项目,只需 2 步 即可引入并使用,无需额外配置。
在业务项目的 pom.xml 中添加依赖(替换为自己的 groupId、artifactId、version):
<!-- 引入自定义字符串工具Starter -->
<dependency>
<groupId>com.example</groupId>
<artifactId>string-util-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>无需配置即可使用默认功能,若需自定义,在 application.yml 中添加如下配置:
# 自定义字符串工具配置(可选)
string:
util:
enabled: true # 开启工具(默认true,可省略)
mask-char: "#" # 脱敏符号改为#(默认*,可自定义)直接注入 StringUtilService,调用方法即可
import com.example.StringUtilService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
// 直接注入Starter提供的Bean(Spring自动创建,无需@Autowired也可,构造注入更规范)
private final StringUtilService stringUtilService;
// 构造注入(推荐,避免空指针)
public TestController(StringUtilService stringUtilService) {
this.stringUtilService = stringUtilService;
}
@GetMapping("/test-starter")
public String testStarter() {
// 测试脱敏功能
String phone = stringUtilService.mask("13812345678");
// 测试大写转换功能
String upperStr = stringUtilService.toUpper("hello custom starter");
return "脱敏结果:" + phone + ",大写结果:" + upperStr;
}
}启动业务项目,访问/test-starter,返回结果如下(默认配置):
脱敏结果:1****8,大写结果:HELLO CUSTOM STARTER若修改 mask-char 为 #,则脱敏结果为:1####8。
Starter 引入后不生效
检查自动配置声明文件路径是否正确(尤其是新版 imports 文件的路径,多一层 spring 目录);
检查自动配置类的全限定名是否与声明文件中的一致;
检查条件注解是否满足(如 @ConditionalOnClass 对应的类是否存在);
检查配置文件中是否关闭了工具(string.util.enabled=false)。
配置文件不生效
检查 @ConfigurationProperties 的 prefix 是否与配置文件中的前缀一致;
检查配置属性类是否有 getter/setter 方法(无 getter/setter 无法绑定配置);
检查自动配置类是否添加了 @EnableConfigurationProperties 注解。
Bean 冲突
给自动配置类的 Bean 添加 @ConditionalOnMissingBean,避免用户自定义 Bean 时出现冲突;
避免 Starter 中创建过多 Bean,仅保留核心通用 Bean。
版本兼容问题
确保同时创建 spring.factories 和 imports 两个声明文件;
依赖版本不要过高,优先选择 2.x 低版本基线,兼容 3.x。
自定义 Spring Boot Starter 是企业级通用组件封装的核心技能,其核心价值是「自动配置、开箱即用、统一管理、复用性强」,能极大减少重复开发,提升项目一致性。