源本科技 | 码上会

Spring Boot 自定义 Starter

2026/04/01
3
0

引言

在 Spring Boot 生态中,Starter(启动器)是核心价值之一,它帮我们实现了自动配置、依赖管理、开箱即用,无需手动繁琐配置和导入依赖,比如spring-boot-starter-webspring-boot-starter-redis都是官方提供的经典 Starter。

但实际业务开发中,我们常会封装通用工具(如日志组件、短信服务、数据库通用操作),想让其他项目也能一键引入、自动生效,这就需要自定义 Spring Boot Starter

核心原理

Spring Boot 自动配置的核心是 @EnableAutoConfiguration,其工作流程可概括为 3 步:

  1. Spring Boot 启动时,会扫描所有依赖包下的自动配置声明文件;

  2. 读取文件中配置的自动配置类

  3. 根据自动配置类上的条件注解,判断是否创建 Bean 并注入 Spring 容器,实现“按需配置、自动生效”。

自定义 Starter 的本质就是

编写自动配置类 → 定义配置属性 → 声明自动配置入口 → 打包供其他项目使用

关键注解

注解

作用

@Configuration

标记当前类为 Spring 配置类,纳入容器扫描

@EnableConfigurationProperties

开启配置属性绑定,将自定义配置类与配置文件关联

@ConditionalOnClass

类路径下存在指定类时,当前配置才生效(避免依赖缺失导致报错)

@ConditionalOnMissingBean

容器中不存在指定 Bean 时,才自动创建(允许用户自定义 Bean 覆盖默认实现)

@ConditionalOnProperty

配置文件中存在指定属性(或满足属性值)时,配置才生效,支持默认值

@ConfigurationProperties

绑定 application.yml/application.properties 中的自定义配置,指定前缀区分配置

开发规范

命名规范

避免与官方冲突

  • 官方 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

打包 Starter

在项目根目录执行 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)

使用自定义 Starter

开箱即用

任何 Spring Boot 项目,只需 2 步 即可引入并使用,无需额外配置。

步骤1:依赖

在业务项目的 pom.xml 中添加依赖(替换为自己的 groupIdartifactIdversion):

<!-- 引入自定义字符串工具Starter -->
<dependency>
    <groupId>com.example</groupId>
    <artifactId>string-util-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

步骤2:配置

无需配置即可使用默认功能,若需自定义,在 application.yml 中添加如下配置:

# 自定义字符串工具配置(可选)
string:
  util:
    enabled: true  # 开启工具(默认true,可省略)
    mask-char: "#" # 脱敏符号改为#(默认*,可自定义)

步骤3:使用

直接注入 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。

常见问题

  1. Starter 引入后不生效

    1. 检查自动配置声明文件路径是否正确(尤其是新版 imports 文件的路径,多一层 spring 目录);

    2. 检查自动配置类的全限定名是否与声明文件中的一致;

    3. 检查条件注解是否满足(如 @ConditionalOnClass 对应的类是否存在);

    4. 检查配置文件中是否关闭了工具(string.util.enabled=false)。

  2. 配置文件不生效

    1. 检查 @ConfigurationPropertiesprefix 是否与配置文件中的前缀一致;

    2. 检查配置属性类是否有 getter/setter 方法(无 getter/setter 无法绑定配置);

    3. 检查自动配置类是否添加了 @EnableConfigurationProperties 注解。

  3. Bean 冲突

    1. 给自动配置类的 Bean 添加 @ConditionalOnMissingBean,避免用户自定义 Bean 时出现冲突;

    2. 避免 Starter 中创建过多 Bean,仅保留核心通用 Bean。

  4. 版本兼容问题

    1. 确保同时创建 spring.factoriesimports 两个声明文件;

    2. 依赖版本不要过高,优先选择 2.x 低版本基线,兼容 3.x。

总结

自定义 Spring Boot Starter 是企业级通用组件封装的核心技能,其核心价值是「自动配置、开箱即用、统一管理、复用性强」,能极大减少重复开发,提升项目一致性。