SpringBoot 封装 starter

starter 机制

SpringBoot 采用约定大于配置思想,starter 是此思想的落地载体

starter 是将功能依赖 + 默认配置 + 自动装配打包成一个 jar,项目只要引入此 jar 即可获得完整能力,无需关心底层到底需要哪些库、怎么配 Bean

starter 规范

  1. 命名

    官方:spring-boot-starter-*​,如 spring-boot-starter-web

    第三方:xxx-spring-boot-starter​,如 mybatis-spring-boot-starter

  2. 版本管理

    统一继承 spring-boot-dependencies BOM,避免传递版本冲突

  3. 模块划分

    复制代码
    xxx-spring-boot-starter(空壳,只管理依赖)
    xxx-spring-boot-autoconfigure(自动配置代码)
    xxx-spring-boot-starter-core(可选,纯业务 API)

    通过合理拆分模块,实现职责单一、可插拔

  4. 自动配置类

    使用注解 @Configuration,@AutoConfiguration 从 3.x 起替代 @Configuration

  5. 条件注解

    使用 @ConditionalOnClass、@ConditionalOnProperty、@ConditionalOnMissingBean 等,防止重复装配、保证可覆盖

  6. 配置元数据

    提供 spring-configuration-metadata.json,辅助 IDE 对配置自动提示

  7. SPI 注册

    配置文件:

    • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(3.x 版本)
    • spring.factories(2.x 版本)

    可同时提供两个版本来提高兼容性

开发实践

以企业中短信功能为场景,封装 SMS starter

SMS starter 分为两个模块

  • sms-spring-boot-autoconfigure:自动配置、核心功能
  • sms-spring-boot-stater:依赖管理

autoconfigure 模块

配置项类

typescript 复制代码
@Data
@ConfigurationProperties(prefix = "sms")
public class SmsProperties {
    // 开关
    private boolean enabled;
    private String accessKey;
    private String secretKey;
    private String region;
}

核心功能接口与实现

typescript 复制代码
// SMS 功能模板类
public interface SmsTemplate {
    SendResult send(String mobile, String sign, String template, Map<String,String> params);
}
​
// 阿里云 SMS 功能实现
public class AliyunSmsTemplate implements SmsTemplate {
    // implement...
}

自动配置类

less 复制代码
@AutoConfiguration // 3.x 版本代替 @Configuration 
@ConditionalOnClass(SmsTemplate.class)
@EnableConfigurationProperties(SmsProperties.class)
@ConditionalOnProperty(prefix = "sms", name = "enabled", matchIfMissing = true)
public class SmsAutoConfiguration {
​
    @Bean
    @ConditionalOnMissingBean
    public SmsTemplate smsTemplate(SmsProperties props) {
        return new AliyunSmsTemplate(props);
    }
}

注册 SPI

创建文件 src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

配置自动配置类全类名

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

配置元数据(可选)

创建文件 src/main/resources/META-INF/additional-spring-configuration-metadata.json

json 复制代码
{
  "properties": [
    {
      "name": "sms.enabled",
      "type": "java.lang.Boolean",
      "defaultValue": true,
      "description": "是否开启短信服务."
    },
    {
      "name": "sms.access-key",
      "type": "java.lang.String",
      "description": "云厂商 AccessKey."
    }
  ]
}

可以配合 spring-boot-configuration-processor​ 或者 spring-boot-properties-maven-plugin 来自动生成此文件

starter 模块

xml 复制代码
<dependencies>
    <!-- 把 autoconfigure 与必要 SDK 全部聚合 -->
    <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>

starter 的使用

引入 starter

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

yaml 配置

yaml 复制代码
sms:
  access-key: xxxxx
  secret-key: xxxxx
  region: cn-hangzhou

注入使用

less 复制代码
@RestController
class RegisterController {
	// 注入 smsTemplate
    @Resource
    private SmsTemplate smsTemplate;

    @PostMapping("/code")
    public String sendCode(@RequestParam String mobile) {
		// 使用 smsTemplate
        // smsTemplate.send(...);
        return "ok";
    }
}

@Enable 注解

在 starter 开发中一个很重要的步骤是注册 SPI,这是 SpringBoot 能自动扫描到 Configuration 从而进行自动配置的原因

除了 SPI 注册的方式,往往还能看到许多应用提供了 @EnableXXX 注解,用于手动指定是否开启功能特性

以 SMS starter 为例,编写一个 @EnableSMS 注解

less 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(SmsConfigurationSelector.class)
public @interface EnableSms {
    /**
     * 是否开启 metrics
     */
    boolean metrics() default true;
}

原理是利用 @Import 把指定配置类直接送进容器,常见三种模式:

less 复制代码
@Import(XXX.class)       → 普通配置类
@Import(Selector.class)  → ImportSelector 可动态返回字符串数组
@Import(Registrar.class) → ImportBeanDefinitionRegistrar 可手动注册 BeanDefinition

实现 SmsConfigurationSelector

typescript 复制代码
public class SmsConfigurationSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata meta) {
        // 拿到注解属性
        MultiValueMap<String, Object> attrs =
                meta.getAllAnnotationAttributes(EnableSms.class.getName());
        boolean metrics = (boolean) attrs.getFirst("metrics");

        List<String> list = new ArrayList<>();
        list.add("com.example.sms.core.SmsAutoConfiguration");
		// 判断是否需要开启 metrics
        if (metrics) {
            list.add("com.example.sms.actuate.SmsMetricsAutoConfiguration");
        }
        return list.toArray(new String[0]);
    }
}

使用方式

less 复制代码
@EnableSms(metrics = false)
@SpringBootApplication
public class DemoApplication { 
	// ...
}

starter 最佳实践:

默认功能使用 SPI 实现自动装配,使用 yaml 实现配置项注入;高级能力配合 @EnableXXX 注解,方便显示开关

相关推荐
Dawson Zhu12 分钟前
面向AI自动化分析的数据仓库建模实践
人工智能·语言模型·架构·制造
黄焖鸡能干四碗21 分钟前
信息安全保障方案(Word文件)
大数据·网络·人工智能·架构·区块链
报错小能手23 分钟前
Go 语言结构 基础语法
开发语言·后端·golang
暗黑小白25 分钟前
参数从哪来、何时来 —— 提取时机与平台化 Slot 管理
人工智能·后端·大模型·ai agent
AI枫林晚1 小时前
DeepSeek Harness 功能与特性解析:一个“一切皆插件“的 Agent 运行时
架构
晴天161 小时前
DeepSeek Harness 插件开发:从零到跑起来-Day18
ai·架构·deepseek
程序员鱼皮1 小时前
DeepSeek Harness 最新邪修曝光!被吹成核弹的极简模式,真的夯吗?
前端·后端·ai编程
刘立军1 小时前
异常与统一封装架构:规范统一返回值、全局异常与参数校验
架构·ai编程
Gopher_HBo1 小时前
请求绑定与校验
后端
长栎1 小时前
你写的撤销功能,99% 是伪 Memento——Undo 不是存个备份那么简单
后端