Spring Boot 自定义 Starter?

2025年 阅读约 15 分钟 面试指南 · Spring Boot

深入解析Spring Boot自定义Starter:自动配置类编写、META-INF/spring/...AutoConfiguration.imports注册、条件注解实战、配置属性绑定、命名规范,附面试模拟问答。

一句话总结

自定义 Starter 三步走:1)写自动配置类(@AutoConfiguration + @ConditionalOnClass + @Bean + @EnableConfigurationProperties);2)注册自动配置(META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中写入配置类全限定名);3)写属性类(@ConfigurationProperties 绑定 application.yml 配置)。命名规范:官方 starter 叫 spring-boot-starter-xxx,第三方叫 xxx-spring-boot-starter。

初级理解

Starter 项目结构

# 自定义 Starter 项目结构 my-spring-boot-starter/ ├── pom.xml └── src/main/ ├── java/com/example/ │ ├── MyService.java # 核心服务类 │ ├── MyProperties.java # 配置属性类 │ └── MyAutoConfiguration.java # 自动配置类 └── resources/ └── META-INF/ └── spring/ └── org.springframework.boot.autoconfigure .AutoConfiguration.imports # 注册文件 # 命名规范 # 官方:spring-boot-starter-web # 第三方:mybatis-spring-boot-starter # 自定义:my-spring-boot-starter

最小实现

# 1. 核心服务类 public class MyService { private String url; private int timeout; public MyService(String url, int timeout) { this.url = url; this.timeout = timeout; } public String call() { return "Calling " + url + " with timeout " + timeout; } } # 2. 配置属性类 @ConfigurationProperties(prefix = "my") public class MyProperties { private String url = "http://localhost:8080"; private int timeout = 3000; // getter/setter } # 3. 自动配置类 @AutoConfiguration @EnableConfigurationProperties(MyProperties.class) @ConditionalOnClass(MyService.class) public class MyAutoConfiguration { @Bean @ConditionalOnMissingBean public MyService myService(MyProperties properties) { return new MyService(properties.getUrl(), properties.getTimeout()); } }

中级深入

注册自动配置

# Spring Boot 2.7+ 注册方式 # 文件路径:META-INF/spring/ # org.springframework.boot.autoconfigure.AutoConfiguration.imports # 文件内容(每行一个配置类全限定名): com.example.MyAutoConfiguration # Spring Boot 2.7 之前注册方式 # 文件路径:META-INF/spring.factories # 文件内容: org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.MyAutoConfiguration # 区别 # 2.7+ 使用专用文件,更简洁 # 2.7 之前使用 spring.factories,所有 SPI 混在一起

条件注解实战

# 多种条件组合 @AutoConfiguration @ConditionalOnClass({MyService.class, RestTemplate.class}) @ConditionalOnProperty(prefix = "my", name = "enabled", havingValue = "true", matchIfMissing = true) @EnableConfigurationProperties(MyProperties.class) public class MyAutoConfiguration { @Bean @ConditionalOnMissingBean public MyService myService(MyProperties properties) { return new MyService(properties.getUrl(), properties.getTimeout()); } @Bean @ConditionalOnMissingBean @ConditionalOnBean(RestTemplate.class) public MyHttpClient myHttpClient(RestTemplate restTemplate) { return new MyHttpClient(restTemplate); } } # 条件说明 # @ConditionalOnClass:classpath 有 MyService 和 RestTemplate # @ConditionalOnProperty:my.enabled=true(默认 true) # @ConditionalOnMissingBean:用户没自定义才创建 # @ConditionalOnBean:容器中有 RestTemplate 才创建 MyHttpClient

高级拓展

@ConfigurationProperties 进阶

# 支持嵌套属性 @ConfigurationProperties(prefix = "my") public class MyProperties { private String url; private int timeout; private Pool pool = new Pool(); // 嵌套对象 public static class Pool { private int maxSize = 10; private int minIdle = 2; // getter/setter } } # application.yml 配置 my: url: https://api.example.com timeout: 5000 pool: max-size: 20 min-idle: 5 # 支持 JSR303 校验 @ConfigurationProperties(prefix = "my") @Validated public class MyProperties { @NotBlank private String url; @Min(1000) @Max(30000) private int timeout = 3000; }

Starter 依赖管理

# pom.xml 关键配置 <dependencies> <!-- 自动配置依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <!-- 配置处理器(生成元数据,IDE 提示) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> </dependencies> # 可选依赖(不强制传递) <dependency> <groupId>com.example</groupId> <artifactId>some-lib</artifactId> <optional>true</optional> <!-- 用户需要时自己引入 --> </dependency>

实战场景

场景:短信服务 Starter

# 使用方只需引入依赖 + 配置 # pom.xml <dependency> <groupId>com.example</groupId> <artifactId>sms-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency> # application.yml sms: provider: aliyun # 阿里云 / 腾讯云 access-key: xxx secret-key: xxx sign-name: 我的应用 template-id: SMS_123456 # 使用 @Autowired private SmsService smsService; public void sendVerifyCode(String phone) { smsService.send(phone, "您的验证码是:123456"); }

面试模拟

面试官:如何自定义一个 Spring Boot Starter?

你:三步:1)写自动配置类(@AutoConfiguration + @ConditionalOnClass + @Bean);2)在 META-INF/spring/...AutoConfiguration.imports 中注册配置类;3)写属性类(@ConfigurationProperties)。引入 Starter 后自动配置生效,用户只需在 application.yml 中配置参数。

面试官:Starter 命名规范是什么?

你:官方 starter 叫 spring-boot-starter-xxx(如 spring-boot-starter-web),第三方叫 xxx-spring-boot-starter(如 mybatis-spring-boot-starter)。这样能一眼区分官方和第三方。