以创建一个发送短信的 Starter(例如 sms-spring-boot-starter
)为例:
一、自定义 Starter 的核心设计
模块 | 作用 |
---|---|
sms-spring-boot-autoconfigure | 包含自动配置类、条件化 Bean 定义和属性配置绑定 |
sms-spring-boot-starter | 空模块,仅依赖 autoconfigure 和其他必要库(如 HTTP 客户端) |
二、实现步骤
1. 创建 Maven 项目结构
sms-spring-boot-starter
├── sms-spring-boot-autoconfigure
│ ├── src/main/java
│ │ └── com/example/sms
│ │ ├── autoconfigure
│ │ │ ├── SmsAutoConfiguration.java // 自动配置类
│ │ │ └── SmsProperties.java // 属性绑定
│ │ └── service
│ │ ├── SmsService.java // 服务接口
│ │ ├── AliyunSmsServiceImpl.java // 阿里云实现
│ │ └── TencentSmsServiceImpl.java // 腾讯云实现
│ └── src/main/resources
│ └── META-INF
│ └── spring.factories // 注册自动配置类
└── sms-spring-boot-starter
└── pom.xml // 仅依赖 autoconfigure
2. 定义属性绑定类 SmsProperties
@ConfigurationProperties(prefix = "sms")
public class SmsProperties {
private String provider = "aliyun"; // 默认阿里云
private String apiKey;
private String apiSecret;
// Getter & Setter
}
3. 定义服务接口 SmsService
public interface SmsService {
void send(String phone, String message);
}
// 阿里云实现
public class AliyunSmsServiceImpl implements SmsService {
private final SmsProperties properties;
public AliyunSmsServiceImpl(SmsProperties properties) {
this.properties = properties;
}
@Override
public void send(String phone, String message) {
// 调用阿里云 SDK
}
}
// 腾讯云实现(类似)
public class TencentSmsServiceImpl implements SmsService { ... }
4. 编写自动配置类 SmsAutoConfiguration
@Configuration
@EnableConfigurationProperties(SmsProperties.class) // 启用属性绑定
@ConditionalOnClass(SmsService.class) // 当类路径存在 SmsService 时生效
public class SmsAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 用户未自定义 SmsService 时生效
@ConditionalOnProperty(prefix = "sms", name = "provider", havingValue = "aliyun")
public SmsService aliyunSmsService(SmsProperties properties) {
return new AliyunSmsServiceImpl(properties);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "sms", name = "provider", havingValue = "tencent")
public SmsService tencentSmsService(SmsProperties properties) {
return new TencentSmsServiceImpl(properties);
}
}
5. 注册自动配置到 META-INF/spring.factories
# src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.sms.autoconfigure.SmsAutoConfiguration
6. 配置 Starter 模块的 pom.xml
<!-- sms-spring-boot-starter/pom.xml -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>sms-spring-boot-autoconfigure</artifactId>
<version>1.0.0</version>
</dependency>
<!-- 其他依赖(如阿里云/腾讯云 SDK) -->
</dependencies>
三、其他项目使用 Starter
1. 引入依赖
<dependency>
<groupId>com.example</groupId>
<artifactId>sms-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
2. 添加配置
# application.properties
sms.provider=tencent
sms.api-key=your-tencent-key
sms.api-secret=your-tencent-secret
3. 直接注入使用
@RestController
public class SmsController {
@Autowired
private SmsService smsService;
@PostMapping("/send-sms")
public String sendSms(@RequestParam String phone, @RequestParam String message) {
smsService.send(phone, message);
return "短信已发送";
}
}
四、高级优化
1. 条件化加载依赖
若 Starter 需要动态引入 SDK(例如根据 provider
自动加载对应 SDK):
@ConditionalOnClass(name = "com.aliyun.dysmsapi20170525.Client") // 检查阿里云 SDK 是否存在
public class AliyunSmsServiceImpl implements SmsService { ... }
2. 自定义健康检查
集成 Spring Boot Actuator 的 Health Indicator:
@Bean
public SmsHealthIndicator smsHealthIndicator(SmsService smsService) {
return new SmsHealthIndicator(smsService);
}
public class SmsHealthIndicator implements HealthIndicator {
private final SmsService smsService;
public SmsHealthIndicator(SmsService smsService) {
this.smsService = smsService;
}
@Override
public Health health() {
// 检查短信服务是否可用
boolean isHealthy = smsService.ping();
return isHealthy ? Health.up().build() : Health.down().build();
}
}
3. 自定义 Starter 元数据
生成配置提示文件 additional-spring-configuration-metadata.json
:
{
"properties": [
{
"name": "sms.provider",
"type": "java.lang.String",
"description": "短信服务提供商(aliyun/tencent)",
"defaultValue": "aliyun"
},
{
"name": "sms.api-key",
"type": "java.lang.String",
"description": "API 密钥"
}
]
}
五、发布 Starter 到 Maven 仓库
- 本地安装:
mvn clean install
- 部署到 Nexus:
mvn deploy -DaltDeploymentRepository=your-repo-id::default::http://your-nexus/repository/maven-releases/
六、总结
关键点 | 说明 |
---|---|
模块分离 | 分离 autoconfigure 和 starter 模块,便于依赖管理 |
条件化配置 | 使用 @ConditionalOn... 系列注解实现灵活加载 |
属性绑定 | 通过 @ConfigurationProperties 实现配置与代码的解耦 |
扩展性 | 允许用户通过自定义 Bean 或覆盖配置灵活扩展功能 |
通过以上步骤,您可以快速创建可复用的 Spring Boot Starter,简化其他项目的集成复杂度。