跳到主要内容

Starter 机制

问题

Spring Boot Starter 是什么?如何自定义一个 Starter?

答案

Starter 的本质

Starter 是 Spring Boot 的 依赖描述符——引入一个 starter 就自动引入该场景所需的所有依赖 + 自动配置。

Starter = 依赖聚合 + 自动配置

Starter 本身通常不包含代码,只做两件事:

  1. 聚合依赖:通过 pom.xml 引入该场景需要的 jar 包
  2. 触发自动配置:依赖中的 spring-boot-autoconfigure 模块包含 @Conditional 配置类

常用官方 Starter

Starter功能
spring-boot-starter-webWeb 开发(Tomcat + Spring MVC)
spring-boot-starter-data-jpaJPA 持久层(Hibernate)
spring-boot-starter-data-redisRedis 缓存
spring-boot-starter-securitySpring Security 认证授权
spring-boot-starter-test测试(JUnit5 + Mockito)
spring-boot-starter-actuator应用监控
spring-boot-starter-validation参数校验(Hibernate Validator)
spring-boot-starter-amqpRabbitMQ 消息队列
spring-boot-starter-cache缓存抽象

命名规范

类型命名格式示例
官方 Starterspring-boot-starter-{name}spring-boot-starter-web
第三方 Starter{name}-spring-boot-startermybatis-spring-boot-starter

自定义 Starter

一个完整的自定义 Starter 通常包含 两个模块

步骤 1:创建自动配置模块

my-spring-boot-autoconfigure/MyProperties.java
@ConfigurationProperties(prefix = "my.sms")
public class SmsProperties {
/** 是否启用 */
private boolean enabled = true;
/** AccessKey */
private String accessKey;
/** SecretKey */
private String secretKey;
/** 签名 */
private String signName;
// getter/setter...
}
my-spring-boot-autoconfigure/SmsService.java
public class SmsService {
private final SmsProperties properties;

public SmsService(SmsProperties properties) {
this.properties = properties;
}

public void send(String phone, String templateCode, Map<String, String> params) {
// 发送短信的实际逻辑
System.out.println("发送短信到 " + phone + ",使用签名:" + properties.getSignName());
}
}
my-spring-boot-autoconfigure/SmsAutoConfiguration.java
@AutoConfiguration
// classpath 中有 SmsService 类才生效
@ConditionalOnClass(SmsService.class)
// 配置 my.sms.enabled=true 时才生效(默认 true)
@ConditionalOnProperty(prefix = "my.sms", name = "enabled", havingValue = "true", matchIfMissing = true)
// 绑定配置属性
@EnableConfigurationProperties(SmsProperties.class)
public class SmsAutoConfiguration {

@Bean
@ConditionalOnMissingBean // 用户未自定义时才注册
public SmsService smsService(SmsProperties properties) {
return new SmsService(properties);
}
}
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.sms.SmsAutoConfiguration

步骤 2:创建 Starter 模块

Starter 模块只有一个 pom.xml,聚合依赖:

sms-spring-boot-starter/pom.xml
<dependencies>
<!-- 引入自动配置模块 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>sms-spring-boot-autoconfigure</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 引入 SMS SDK -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
</dependency>
</dependencies>

步骤 3:使用

application.yml
my:
sms:
access-key: xxx
secret-key: xxx
sign-name: "MyApp"
使用示例
@Service
public class NotificationService {
@Autowired
private SmsService smsService; // 自动注入

public void notifyUser(String phone) {
smsService.send(phone, "SMS_001", Map.of("code", "123456"));
}
}

常见面试问题

Q1: Spring Boot Starter 的原理是什么?

答案

Starter 是依赖描述符,本身不含代码。它通过 Maven/Gradle 聚合了该场景所需的所有依赖,引入后 Spring Boot 的自动配置机制(@EnableAutoConfiguration)会根据 classpath 中的类和 @Conditional 条件注解自动注册相关 Bean。

Q2: 如何自定义一个 Starter?

答案

  1. 创建 autoconfigure 模块:编写 @AutoConfiguration 配置类 + @ConfigurationProperties 属性类 + 业务类
  2. 注册配置类到 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  3. 创建 starter 模块:只有 pom.xml,引入 autoconfigure 模块和所需依赖
  4. 使用 @ConditionalOnMissingBean 保证用户自定义优先

Q3: 为什么 Starter 要分成两个模块?

答案

  • autoconfigure 模块:包含自动配置逻辑,可以被依赖但不强制引入所有第三方依赖(使用 optional 标记)
  • starter 模块:面向用户,聚合所有必要依赖

分离后,如果用户只想用部分功能,可以直接依赖 autoconfigure 模块并自行选择依赖。不过小型项目中合并成一个模块也是可以的。

Q4: spring-boot-starter-parent 的作用?

答案

spring-boot-starter-parent 是一个父 POM,提供:

  • 依赖版本管理:统一管理所有 Spring 生态的依赖版本,避免版本冲突
  • 默认配置:编译版本、编码格式、资源过滤
  • 插件管理:spring-boot-maven-plugin 等

如果项目已有父 POM,可以用 spring-boot-dependencies 的 BOM 方式替代。

相关链接