Spring Boot 自定义 Starter 完整实战手册
Spring Boot 自定义 Starter 完整实战手册
一、核心概念与项目结构
1. 什么是 Starter?
- 本质:预配置模块 = 依赖集合 + 自动配置类 + 默认实现
 - 核心价值: 
  
- 统一技术栈:团队快速复用标准组件
 - 简化配置:隐藏复杂实现细节(如连接池参数)
 - 按需加载:通过 
@Conditional实现特性开关 
 
2. 项目目录结构(以短信服务 Starter 为例)
my-sms-starter/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           ├── config/
│   │   │           │   ├── SmsAutoConfiguration.java  # 自动配置类
│   │   │           │   └── SmsProperties.java         # 配置属性类
│   │   │           └── service/
│   │   │               ├── SmsService.java             # 核心服务接口
│   │   │               └── impl/                       # 多厂商实现
│   │   │                   ├── AliyunSmsImpl.java
│   │   │                   └── TencentSmsImpl.java
│   │   └── resources/
│   │       ├── META-INF/
│   │       │   ├── spring/
│   │       │   │   └── org.springframework.boot.autoconfigure.AutoConfiguration.imports  # Spring Boot 3.x+
│   │       │   └── spring.factories                   # Spring Boot 2.x
│   │       └── application.yml                        # 默认配置(可选)
│   └── test/                                          # 单元测试
└── pom.xml                                            # Maven 依赖管理
 
二、详细实现步骤(以短信服务为例)
1. 创建 Maven 项目(pom.xml)
<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>my-sms-starter</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.14</version> <!-- 确保与 Spring Boot 版本兼容 -->
        <relativePath/> <!-- 直接继承 Spring Boot 依赖管理 -->
    </parent>
    <dependencies>
        <!-- Spring Boot 自动配置支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <!-- 依赖管理,避免传递冲突 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <scope>provided</scope>  
        </dependency>
        <!-- 处理 @ConfigurationProperties 自动绑定 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional> 
        </dependency>
        <!-- Lombok,简化 Java 代码 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- JUnit 5(仅测试环境使用) -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- Spring Boot 编译插件 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
 
注意:若需支持 Spring Boot 3.x,需 JDK 17+ 并检查依赖兼容性。
2. 编写配置属性类(绑定 YAML 参数)
// SmsProperties.java
@Data
@ConfigurationProperties(prefix = "sms")  // 配置前缀 sms.xxx
public class SmsProperties {
    /**
     * 短信平台类型(aliyun/tencent/huawei)
     */
    private String type = "aliyun";
    private String apiKey;     // 对应 sms.api-key
    private String endpoint = "https://api.sms.com";  // 默认值
    private int retry = 3;     // 默认重试次数
}
 
作用:将 application.yml 中的参数映射到 Java 对象。
3. 编写自动配置类(核心)
// SmsAutoConfiguration.java
@Configuration
@EnableConfigurationProperties(SmsProperties.class)  // 启用属性绑定
@ConditionalOnClass(SmsService.class)               // 检测类路径是否存在 SmsService
@AutoConfigureAfter(CacheAutoConfiguration.class)  // 明确装配顺序
public class SmsAutoConfiguration {
    // 阿里云短信服务 Bean
    @Bean
    @ConditionalOnMissingBean  // 用户未自定义时创建默认 Bean
    @ConditionalOnProperty(prefix = "sms", name = "type", havingValue = "aliyun")
    public SmsService aliyunSmsService(SmsProperties properties) {
        return new AliyunSmsImpl(properties.getApiKey(), properties.getEndpoint(), properties.getRetry());
    }
    // 腾讯云短信服务 Bean
    @Bean
    @ConditionalOnMissingBean  // 用户未自定义时创建默认 Bean
    @ConditionalOnProperty(prefix = "sms", name = "type", havingValue = "tencent")
    public SmsService tencentSmsService(SmsProperties properties) {
        return new TencentSmsImpl(properties.getApiKey(), properties.getEndpoint(), properties.getRetry());
    }
}
 
条件注解解析:
@ConditionalOnClass:检测是否存在特定类(如 RedisTemplate)@ConditionalOnWebApplication:仅在 Web 环境生效
4. 服务接口与实现(策略模式)
// SmsService.java
public interface SmsService {
    boolean send(String mobile, String content);
}
// AliyunSmsImpl.java
public class AliyunSmsImpl implements SmsService {
    private final String apiKey;
    private final String endpoint;
    private final int retry;
    // 使用带参数的构造函数进行初始化
    public AliyunSmsImpl(String apiKey, String endpoint, int retry) {
        this.apiKey = apiKey;
        this.endpoint = endpoint;
        this.retry = retry;
    }
    
    @Override
    public boolean send(String mobile, String content) {
        // 阿里云 SDK 具体实现
        System.out.println("调用阿里云短信接口,apiKey:" + apiKey + ", endpoint:" + ", retry:" + retry + ", mobile:" + mobile + ", content:" + content);
        return true;
    }
}
// TencentSmsImpl.java
public class TencentSmsImpl implements SmsService {
    private final String apiKey;
    private final String endpoint;
    private final int retry;
    // 使用带参数的构造函数进行初始化
    public TencentSmsImpl(String apiKey, String endpoint, int retry) {
        this.apiKey = apiKey;
        this.endpoint = endpoint;
        this.retry = retry;
    }
    
    @Override
    public boolean send(String mobile, String content) {
        // 腾讯云 SDK 具体实现
        System.out.println("调用腾讯云短信接口,apiKey:" + apiKey + ", endpoint:" + ", retry:" + retry + ", mobile:" + mobile + ", content:" + content);
        return true;
    }
}
 
5. 注册自动配置类(版本差异)
-  
Spring Boot 2.x:
在src/main/resources/META-INF/spring.factories添加:org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.config.SmsAutoConfiguration -  
Spring Boot 3.x:
在src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports添加:com.example.config.SmsAutoConfiguration重要提示:Spring Boot 2.7+ 已弃用
spring.factories,必须使用新路径。 
6. 打包发布
# 安装到本地仓库
mvn clean install -DskipTests
# 发布到 Nexus 私服
mvn deploy -DaltDeploymentRepository=nexus::default::http://nexus.example.com/repository/maven-releases/
 
三、使用示例
1. 引入依赖
<dependency>
    <groupId>com.example</groupId>
    <artifactId>my-sms-starter</artifactId>
    <version>1.0.0</version>
</dependency>
 
2. 配置参数
sms:
  type: "tencent"
  api-key: "d0d0b33f-87e2-4aac"
  endpoint: "https://sms.cloud.prod"
  retry: 2
 
3. 业务代码
@Service
public class TestSmsService {
    private final SmsService smsService;
    public TestSmsService(SmsService smsService) {
        this.smsService = smsService;
    }
    public void sendSms( ) {
        smsService.send("13800138000","短信内容6666");
    }
}
 
四、常见问题排查
| 问题现象 | 解决方案 | 
|---|---|
| 配置不生效 | 检查 @ConfigurationProperties 的 prefix 是否匹配 YAML | 
| Bean 未创建 | 确认类路径存在 @ConditionalOnClass 指定的类 | 
| Spring Boot 3.x 不兼容 | 使用 AutoConfiguration.imports 替代 spring.factories | 
| 依赖冲突 | 在 starter 模块中声明 <optional>true</optional> | 
五、实际案例参考
-  
短信服务 Starter
- 功能:支持阿里云、腾讯云、华为云动态切换,内置签名验证和模板管理。
 - 源码:参考开源项目 
sms-spring-boot-starter(Gitee)。 
 -  
分布式锁 Starter
- 功能:封装 Redis/Redisson/ZooKeeper 实现,支持注解式锁(
@DistributedLock)。 - 设计:通过 
@ConditionalOnClass按需加载不同实现。 
 - 功能:封装 Redis/Redisson/ZooKeeper 实现,支持注解式锁(
 
