用过SpringBoot的人都有体会,想集成Redis只需引入spring-boot-starter-data-redis,想用Web开发就引入spring-boot-starter-web,连一行配置代码都不用写,功能就自动生效了。这种开箱即用的体验,靠的就是Starter场景启动器机制。那么官方的Starter是如何被Spring自动识别的?我们自己能不能也写一个Starter,让团队的其他项目直接引入依赖就能用?答案是肯定的,这篇文章就从原理到实操,完整演示一遍自定义Starter的全过程。

一、先搞懂Starter的自动装配原理
很多人只知道引入依赖就能用,却不知道SpringBoot在背后做了什么。实际上,SpringBoot项目启动时,@SpringBootApplication注解中包含的@EnableAutoConfiguration注解会触发自动装配流程。这个注解通过@Import引入了一个选择器,选择器会去读取所有jar包中META-INF/spring.factories文件(SpringBoot 2.7之后也可以使用META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件),把里面登记的自动配置类全量加载进来。
需要注意的是,这些自动配置类并不是全部都会生效。它们内部通常配合@Conditional系列条件注解使用,比如@ConditionalOnClass判断类路径下是否存在某个类,@ConditionalOnMissingBean判断容器中是否还没有某个Bean,@ConditionalOnProperty判断配置文件中是否配置了某个属性。只有条件全部满足,配置类里定义的Bean才会真正注册到容器中。这套机制既保证了自动装配的智能性,又给使用者留出了覆盖默认配置的余地。
一个标准的Starter通常包含两个部分:一个是自动配置模块,负责编写配置类和条件注解;另一个是依赖聚合,把功能所需的相关依赖统一打包。官方向的Starter命名格式是spring-boot-starter-xxx,而自定义Starter官方建议命名为xxx-spring-boot-starter,通过命名就能区分是官方提供的还是第三方开发的。
二、动手搭建自定义Starter工程
假设我们要做一个简单的问候功能Starter,引入依赖后,项目自动注册一个GreetingService,并且可以通过配置文件自定义问候语前缀。首先创建一个Maven工程,命名为demo-spring-boot-starter,在pom.xml中引入自动配置相关的依赖。
<dependencies>
<!-- 编写自动配置需要用到SpringBoot的自动装配注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.7.18</version>
</dependency>
<!-- 属性绑定需要用到configuration processor -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
<version>2.7.18</version>
</dependency>
</dependencies>接下来编写属性配置类,把配置文件中以demo.greeting为前缀的属性映射进来,并设置一个默认值,这样即使使用方不配置任何东西,Starter也能正常工作。
@ConfigurationProperties(prefix = "demo.greeting")
public class GreetingProperties {
/** 问候语前缀,默认为hello */
private String prefix = "hello";
/** 问候次数 */
private Integer count = 1;
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}然后是核心的业务类,这个类就是使用方真正要调用的功能Bean,它读取配置属性,对外提供问候方法。
public class GreetingService {
private final GreetingProperties properties;
public GreetingService(GreetingProperties properties) {
this.properties = properties;
}
public String sayHello(String name) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < properties.getCount(); i++) {
sb.append(properties.getPrefix())
.append(", ")
.append(name)
.append(System.lineSeparator());
}
return sb.toString();
}
}三、编写自动配置类并注册Starter
自动配置类是整个Starter的灵魂,它决定了在什么条件下、注册哪些Bean。这里的写法很有讲究:用@EnableConfigurationProperties开启属性绑定,用@ConditionalOnMissingBean保证只有容器中没有同名Bean时才注册默认实现,这样使用方如果想自己定义一个GreetingService,可以直接覆盖默认行为。
@AutoConfiguration
@ConditionalOnClass(GreetingService.class)
@EnableConfigurationProperties(GreetingProperties.class)
public class GreetingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public GreetingService greetingService(GreetingProperties properties) {
return new GreetingService(properties);
}
}配置类写完后,最关键的一步是注册。在工程的resources目录下创建META-INF/spring目录,放入org.springframework.boot.autoconfigure.AutoConfiguration.imports文件(适用于SpringBoot 2.7及以上版本),文件内容只有一行,即配置类的全限定名:
com.example.starter.config.GreetingAutoConfiguration
如果你使用的是较老版本的SpringBoot,则需要改用META-INF/spring.factories文件,内容格式如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.starter.config.GreetingAutoConfiguration
注意上面properties文件里的反斜杠是换行续接符,多行配置时必须保留。最后执行mvn clean install把Starter安装到本地仓库,或者发布到公司私服,供其他项目引用。
四、在业务项目中引入并验证效果
验证环节很简单。新建一个SpringBoot项目,在pom.xml中引入我们刚打好的Starter依赖,然后在application.properties中配置自定义属性,写一个测试接口直接注入GreetingService调用即可。
<dependency>
<groupId>com.example</groupId>
<artifactId>demo-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
demo.greeting.prefix=你好 demo.greeting.count=3
@RestController
public class TestController {
@Autowired
private GreetingService greetingService;
@GetMapping("/greet")
public String greet() {
return greetingService.sayHello("张三");
}
}启动项目访问http://127.0.0.1:8080/greet,如果页面上出现三行问候信息,说明自动装配已经生效。如果没生效,优先排查两点:一是imports文件或spring.factories文件的路径和文件名是否完全正确,路径大小写敏感,META-INF写错一个字母都会导致加载失败;二是配置类上是否漏掉了会被组件扫描识别的注册入口。
另外有几个实践建议:自定义Starter尽量不依赖具体的Web环境,保持功能纯粹;所有默认Bean都加上@ConditionalOnMissingBean,给使用方留出覆盖空间;对外暴露的属性类要写好默认值和注释,最好配合spring-boot-configuration-processor,这样使用方在IDE里写配置时能获得自动提示,体验会好很多。掌握了这套流程,你就不仅能自定义Starter,也能真正读懂SpringBoot官方那些Starter的源码结构了。
SpringBoot自定义StarterSpringBoot Starters自动装配修改时间:2026-09-05 17:22:55