SpringBoot:封装 starter

01 Starter 核心机制

SpringBoot 核心思想是约定大于配置,而 Starter 正是这一思想的核心落地载体。

简单来说,Starter 把某一类功能的依赖管理、默认配置、自动装配逻辑打包成一个独立 Jar 包。

项目只需引入这个 Jar 包,就能直接使用对应功能,无需关心底层依赖的具体版本、Bean 如何配置等细节。

02 Starter 开发规范

想要开发出符合 SpringBoot 生态、易维护的 Starter,需遵循以下核心规范:

02.1 命名规范

• 官方 Starter:统一采用 spring-boot-starter-* 命名格式,例如 spring-boot-starter-web。

• 第三方 Starter:推荐使用 xxx-spring-boot-starter 格式,例如 mybatis-spring-boot-starter。

02.2 版本管理规范

必须统一继承 spring-boot-dependencies BOM(物料清单),避免因依赖传递导致的版本冲突问题。

02.3 模块划分规范

合理的模块拆分能让 Starter 职责单一、支持可插拔,推荐拆分方式:

xxx-spring-boot-starter(空壳模块,仅做依赖聚合管理)

xxx-spring-boot-autoconfigure(核心模块,包含自动配置代码)

xxx-spring-boot-starter-core(可选模块,存放纯业务 API 逻辑)

02.4 自动配置类规范

SpringBoot 3.x 版本起,推荐使用 @AutoConfiguration 注解替代传统的 @Configuration 注解定义自动配置类。

02.5 条件注解规范

必须合理使用条件注解(如 @ConditionalOnClass、@ConditionalOnProperty、@ConditionalOnMissingBean),既能避免 Bean 重复装配,也能保证用户可自定义覆盖默认 Bean。

02.6 配置元数据规范

建议提供 spring-configuration-metadata.json 文件,辅助 IDE 实现配置项的自动提示,提升用户使用体验。

02.7 SPI 注册规范

自动配置类需要通过 SPI 机制让 SpringBoot 扫描到,不同版本配置方式不同:

• SpringBoot 3.x:配置文件路径 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports。

• SpringBoot 2.x:配置文件路径 META-INF/spring.factories。

建议同时兼容两个版本的配置方式,提升 Starter 兼容性。

03 Starter 开发实战:以短信(SMS)功能为例

下面以企业常用的短信发送功能为例,完整演示 Starter 的开发流程。

本次实战将 Starter 拆分为两个核心模块:

• sms-spring-boot-autoconfigure:负责自动配置逻辑和核心业务实现。

• sms-spring-boot-starter:仅做依赖聚合管理,简化用户引入操作。

03.1 autoconfigure 模块开发

该模块是 Starter 的核心,包含配置项定义、核心功能实现、自动配置逻辑等。

(1)配置项类定义

用于绑定用户在配置文件中定义的短信相关配置,通过 @ConfigurationProperties 指定配置前缀。

java 复制代码
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * 短信配置项类
 * 绑定配置文件中以 "sms" 为前缀的配置项
 */
@Data // Lombok 注解,自动生成getter/setter/toString等方法
@ConfigurationProperties(prefix = "sms") // 指定配置前缀
public class SmsProperties {
    // 短信功能总开关
    private boolean enabled = true;
    // 云厂商AccessKey(访问密钥)
    private String accessKey;
    // 云厂商SecretKey(密钥)
    private String secretKey;
    // 云厂商地域(如阿里云的cn-hangzhou)
    private String region;
}

(2)核心功能接口与实现

定义短信发送的标准接口,以及阿里云短信的具体实现(可扩展其他厂商)。

java 复制代码
import java.util.Map;

/**
 * 短信发送模板接口
 * 定义短信发送的标准方法,适配不同云厂商实现
 */
public interface SmsTemplate {
    /**
     * 发送短信
     * @param mobile 接收短信的手机号
     * @param sign 短信签名
     * @param template 短信模板编码
     * @param params 短信模板参数(如验证码、有效期等)
     * @return 发送结果(自定义SendResult类,包含发送状态、回执ID等)
     */
    SendResult send(String mobile, String sign, String template, Map<String,String> params);
}

/**
 * 阿里云短信模板实现类
 * 实现SmsTemplate接口,对接阿里云短信SDK
 */
public class AliyunSmsTemplate implements SmsTemplate {

    // 注入短信配置项
    private final SmsProperties smsProperties;

    // 构造方法注入配置
    public AliyunSmsTemplate(SmsProperties smsProperties) {
        this.smsProperties = smsProperties;
        // 初始化阿里云短信客户端(此处省略SDK初始化逻辑)
    }

    /**
     * 实现短信发送方法
     * @param mobile 手机号
     * @param sign 短信签名
     * @param template 模板编码
     * @param params 模板参数
     * @return 发送结果
     */
    @Override
    public SendResult send(String mobile, String sign, String template, Map<String, String> params) {
        // 1. 构建阿里云短信请求参数
        // 2. 调用阿里云短信SDK发送短信
        // 3. 解析SDK返回结果,封装为SendResult返回
        // 此处省略具体SDK调用逻辑,可参考阿里云官方文档
        return new SendResult(true, "发送成功", System.currentTimeMillis() + "");
    }
}

/**
 * 短信发送结果封装类
 * 简化示例,实际可扩展更多字段(如错误码、错误信息等)
 */
class SendResult {
    // 是否发送成功
    private boolean success;
    // 提示信息
    private String msg;
    // 短信回执ID
    private String bizId;

    public SendResult(boolean success, String msg, String bizId) {
        this.success = success;
        this.msg = msg;
        this.bizId = bizId;
    }

    // 省略getter/setter方法
}

(3)自动配置类定义

核心配置类,控制 Bean 的创建条件和逻辑,保证按需装配、可覆盖。

java 复制代码
import org.springframework.boot.autoconfigure.AutoConfiguration;
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;

/**
 * 短信自动配置类
 * SpringBoot 3.x 推荐使用@AutoConfiguration替代@Configuration
 */
@AutoConfiguration // 替代3.x之前的@Configuration,标识自动配置类
@ConditionalOnClass(SmsTemplate.class) // 仅当类路径下存在SmsTemplate时才生效
@EnableConfigurationProperties(SmsProperties.class) // 启用配置项绑定,让SmsProperties生效
@ConditionalOnProperty(prefix = "sms", name = "enabled", matchIfMissing = true) // 仅当sms.enabled为true时生效,默认开启
public class SmsAutoConfiguration {

    /**
     * 注册SmsTemplate Bean
     * @param props 注入短信配置项(Spring自动绑定)
     * @return 阿里云短信模板实例
     */
    @Bean // 向Spring容器注册Bean
    @ConditionalOnMissingBean // 仅当容器中不存在SmsTemplate类型的Bean时才创建,允许用户自定义覆盖
    public SmsTemplate smsTemplate(SmsProperties props) {
        return new AliyunSmsTemplate(props);
    }
}

(4)SPI 注册配置

让 SpringBoot 能扫描到自动配置类,3.x 版本需创建以下文件:

java 复制代码
文件路径:src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

文件内容(配置自动配置类的全类名):

java 复制代码
com.example.sms.boot.SmsAutoConfiguration

(5)配置元数据(可选)

辅助 IDE 实现配置项的自动提示,提升用户体验,创建以下文件:

文件路径:src/main/resources/META-INF/additional-spring-configuration-metadata.json

文件内容:

java 复制代码
{
  "properties": [
    {
      "name": "sms.enabled",
      "type": "java.lang.Boolean",
      "defaultValue": true,
      "description": "短信服务总开关,默认开启。"
    },
    {
      "name": "sms.access-key",
      "type": "java.lang.String",
      "description": "云厂商短信服务的AccessKey,必填。"
    },
    {
      "name": "sms.secret-key",
      "type": "java.lang.String",
      "description": "云厂商短信服务的SecretKey,必填。"
    },
    {
      "name": "sms.region",
      "type": "java.lang.String",
      "description": "云厂商短信服务的地域编码(如阿里云cn-hangzhou)。"
    }
  ]
}

可借助 spring-boot-configuration-processor 依赖或 spring-boot-properties-maven-plugin 插件自动生成该文件,减少手动编写成本。

03.2 starter 模块开发

该模块为"空壳"模块,仅聚合依赖,简化用户引入操作。

Maven 依赖配置示例:

java 复制代码
<dependencies>
    <!-- 聚合autoconfigure模块,核心逻辑依赖 -->
    <dependency>
        <groupId>com.example.sms</groupId>
        <artifactId>sms-spring-boot-autoconfigure</artifactId>
        <version>${project.version}</version>
    </dependency>
    <!-- 阿里云短信SDK,无需用户单独引入 -->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>dysmsapi20170525</artifactId>
        <version>2.0.24</version>
    </dependency>
</dependencies>

03.3 Starter 使用示例

用户只需两步即可使用开发好的短信 Starter。

(1)引入 Starter 依赖

在项目的 pom.xml 中引入:

java 复制代码
<dependency>
    <groupId>com.example.sms</groupId>
    <artifactId>sms-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

(2)配置短信参数

在 application.yml/application.properties 中配置:

java 复制代码
sms:
  access-key: your-aliyun-access-key # 替换为实际AccessKey
  secret-key: your-aliyun-secret-key # 替换为实际SecretKey
  region: cn-hangzhou # 替换为实际地域
  # enabled: true # 默认开启,可省略

(3)注入使用

在业务代码中注入 SmsTemplate 即可使用:

java 复制代码
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * 注册控制器示例
 * 演示短信验证码发送功能
 */
@RestController
public class RegisterController {

    // 注入Spring容器中的SmsTemplate Bean(自动配置类创建)
    @Resource
    private SmsTemplate smsTemplate;

    /**
     * 发送注册验证码
     * @param mobile 手机号
     * @return 操作结果
     */
    @PostMapping("/send/register/code")
    public String sendRegisterCode(@RequestParam String mobile) {
        // 1. 生成6位随机验证码
        String code = String.valueOf((int)((Math.random()*9+1)*100000));
        // 2. 构建短信模板参数
        Map<String, String> params = new HashMap<>();
        params.put("code", code);
        params.put("expireTime", "5"); // 有效期5分钟
        // 3. 调用短信模板发送短信
        SendResult result = smsTemplate.send(mobile, "XX平台", "SMS_123456789", params);
        // 4. 处理发送结果
        if (result.isSuccess()) {
            return "验证码发送成功,请注意查收";
        } else {
            return "验证码发送失败:" + result.getMsg();
        }
    }
}

04 进阶:@Enable 注解的使用

除了通过 SPI 实现自动装配,还可以通过 @EnableXXX 注解手动控制 Starter 功能的开启/关闭,适用于高级能力的显式开关。

以短信 Starter 为例,实现 @EnableSms 注解,支持手动开启/关闭指标监控(metrics)能力。

04.1 定义 @EnableSms 注解

java 复制代码
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;

/**
 * 开启短信功能注解
 * 可手动控制是否开启短信功能及扩展能力(如metrics)
 */
@Target(ElementType.TYPE) // 注解作用于类/接口
@Retention(RetentionPolicy.RUNTIME) // 运行时生效
@Documented // 生成文档时包含该注解
@Import(SmsConfigurationSelector.class) // 导入配置选择器,动态加载配置类
public @interface EnableSms {
    /**
     * 是否开启短信发送指标监控(如发送成功率、耗时等)
     * @return 默认开启
     */
    boolean metrics() default true;
}

04.2 实现配置选择器

通过 ImportSelector 动态选择需要加载的配置类:

java 复制代码
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.annotation.MultiValueMap;
import org.springframework.core.type.AnnotationMetadata;
import java.util.ArrayList;
import java.util.List;

/**
 * 短信配置选择器
 * 根据@EnableSms注解的属性,动态加载对应的配置类
 */
public class SmsConfigurationSelector implements ImportSelector {

    /**
     * 选择需要导入的配置类全类名
     * @param annotationMetadata 注解元数据(包含@EnableSms的属性)
     * @return 配置类全类名数组
     */
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // 1. 获取@EnableSms注解的所有属性
        MultiValueMap<String, Object> attrs = annotationMetadata.getAllAnnotationAttributes(EnableSms.class.getName());
        // 2. 获取metrics属性值(默认true)
        boolean metrics = attrs != null && (boolean) attrs.getFirst("metrics");

        // 3. 构建需要导入的配置类列表
        List<String> configClasses = new ArrayList<>();
        // 核心短信自动配置类必加载
        configClasses.add("com.example.sms.core.SmsAutoConfiguration");
        // 如果开启metrics,加载指标监控配置类
        if (metrics) {
            configClasses.add("com.example.sms.actuate.SmsMetricsAutoConfiguration");
        }

        // 4. 转换为数组返回
        return configClasses.toArray(new String[0]);
    }
}

04.3 使用 @EnableSms 注解

在 SpringBoot 启动类上添加注解,显式控制功能:

java 复制代码
import com.example.sms.annotation.EnableSms;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 应用启动类
 * 通过@EnableSms手动关闭metrics能力
 */
@EnableSms(metrics = false) // 开启短信功能,关闭指标监控
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

05 Starter 最佳实践总结

  1. 基础功能:通过 SPI 机制实现自动装配,配置项通过 yaml/properties 注入,降低用户使用成本。
  2. 高级能力:配合 @EnableXXX 注解实现显式开关,让用户可按需开启扩展功能(如监控、日志等)。
  3. 兼容性:同时兼容 SpringBoot 2.x 和 3.x 的 SPI 注册方式,提升 Starter 适用范围。
  4. 可扩展:核心接口抽象化(如 SmsTemplate),方便扩展不同厂商的实现(阿里云、腾讯云等)。
  5. 易用性:提供配置元数据,辅助 IDE 自动提示,完善注释文档,降低用户接入门槛。
相关推荐
STARSpace88882 小时前
SpringBoot 整合个推推送
java·spring boot·后端·消息推送·个推
码农幻想梦2 小时前
实验八 获取请求参数及域对象共享数据
java·开发语言·servlet
a努力。2 小时前
2026 AI 编程终极套装:Claude Code + Codex + Gemini CLI + Antigravity,四位一体实战指南!
java·开发语言·人工智能·分布式·python·面试
Dylan的码园2 小时前
功能包介绍 : calendar
java·jvm·eclipse
二川bro2 小时前
Java集合类框架的基本接口有哪些?
java·开发语言·python
Marktowin3 小时前
玩转 ZooKeeper
后端
菜鸟233号3 小时前
力扣213 打家劫舍II java实现
java·数据结构·算法·leetcode
panzer_maus3 小时前
Redis简单介绍(3)-持久化的实现
java·redis·mybatis
毕设源码-邱学长3 小时前
【开题答辩全过程】以 民宿在线预定平台的设计与实现为例,包含答辩的问题和答案
java·eclipse