SpringBoot自定义Starter
ps:如果这篇帖子对于还在找工作和找实习的你有所帮助,可以关注我,给本贴点赞、评论、收藏并订阅专栏;同时不要吝啬您的花花
一、先搞懂:Starter核心原理
SpringBoot Starter的本质是自动配置+依赖封装,目的是简化第三方组件/自定义功能的集成成本,无需手动编写大量配置,只需引入Starter即可开箱即用。
核心机制:
- 自动配置类:标记@Configuration,定义Bean创建规则
- 条件注解:控制Bean的创建时机(如依赖存在、配置开启时才加载)
- SPI机制:SpringBoot启动时扫描指定文件,加载自动配置类
- 依赖传递:Starter内部封装所需依赖,引入方无需重复导包
SpringBoot 2.7+ 废弃了传统的spring.factories,改用META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件注册自动配置类,本文以新版规范为主,同时兼容低版本写法。
Starter自动装配全生命周期链路
针对本次hello-spring-boot-starter,自动装配并非随机生效,而是遵循SpringBoot固定的SPI+容器托管流程,全程分为启动扫描→配置绑定→Bean注册→业务注入四大核心阶段,每一步都有严格的触发规则:
阶段1:项目启动,SPI机制扫描自动配置类
- SpringBoot项目启动时,执行自动配置加载器,扫描类路径下的指定SPI文件
- 定位到Starter中resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
- 读取文件内的全限定类名,加载HelloAutoConfiguration自动配置类,将其纳入Spring容器的配置管理池
阶段2:开启配置绑定,映射yml参数
- 自动配置类上的@EnableConfigurationProperties(HelloProperties.class)触发生效,开启配置绑定功能
- 扫描HelloProperties类上的@ConfigurationProperties(prefix = "hello")注解
- 读取项目application.yml中hello.开头的配置项,通过setter方法赋值给HelloProperties的对应字段
- 生成携带配置参数的HelloProperties单例Bean,存入Spring容器
阶段3:条件校验,注册核心业务Bean
- 校验自动配置类上的@ConditionalOnClass(HelloService.class):类路径存在HelloService则继续,否则跳过装配
- 执行@Bean修饰的方法,Spring容器按类型自动注入已存在的HelloProperties Bean(无需@Autowired)
- 校验@ConditionalOnMissingBean:容器无自定义HelloService Bean时,执行new HelloService(helloProperties)创建实例
- 将HelloService实例注册为Spring容器Bean,交由容器管理生命周期
阶段4:业务调用,容器注入Bean使用
- 测试项目中通过@Resource/@Autowired注解声明HelloService属性
- Spring容器根据类型匹配,将已注册的HelloService Bean注入到Controller中
- 调用sayHello()方法,底层读取HelloProperties的配置参数,返回拼接后的结果
链路核心总结:SPI文件定位配置类 → 注解激活配置绑定 → 条件判断创建Bean → 容器托管注入使用,全程无需手动扫描、无需手动new对象,实现真正的开箱即用。
二、前期准备
1. 环境要求
- JDK 8+
- Maven 3.6+
- SpringBoot 2.7.x / 3.x(本文以2.7.15为例)
2. 项目命名规范
官方Starter命名:spring-boot-starter-xxx;自定义Starter推荐:xxx-spring-boot-starter(避免与官方冲突)。
示例:本次创建hello-spring-boot-starter,实现自定义问候功能的自动装配。
三、分步实现:自定义Starter
Step1:创建Maven空项目(无启动类)
Starter是普通Maven项目,无需SpringBoot启动类,仅作为依赖包存在。创建完成后,配置pom.xml核心依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 自定义Starter坐标 -->
<groupId>com.example</groupId>
<artifactId>hello-spring-boot-starter</artifactId>
<version>1.0.0</version>
<!-- 父工程:统一SpringBoot版本 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.15</version>
<relativePath/>
</parent>
<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>
<!-- 打包配置:跳过测试,避免打包失败 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Step2:编写配置属性类
用于绑定application.yml中的自定义配置,实现参数可配置。
package com.example.hello.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 自定义配置绑定类
* prefix:配置文件中的前缀
*/
@ConfigurationProperties(prefix = "hello")
public class HelloProperties {
/**
* 问候前缀,默认值:Hello
*/
private String prefix = "Hello";
/**
* 问候后缀,默认值:!
*/
private String suffix = "!";
// getter & setter
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
}
Step3:编写业务功能类
定义Starter提供的核心业务逻辑,后续由自动配置类加载为Bean。
package com.example.hello.service;
import com.example.hello.config.HelloProperties;
public class HelloService {
private final HelloProperties helloProperties;
// 构造注入配置属性
public HelloService(HelloProperties helloProperties) {
this.helloProperties = helloProperties;
}
/**
* 自定义问候方法
* @param name 用户名
* @return 拼接后的问候语
*/
public String sayHello(String name) {
return helloProperties.getPrefix() + " " + name + helloProperties.getSuffix();
}
}
Step4:编写自动配置类
核心类,控制HelloService的创建条件,实现自动装配。
package com.example.hello.config;
import com.example.hello.service.HelloService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 自动配置类
*/
@Configuration
// 当HelloService类存在时,才加载该配置
@ConditionalOnClass(HelloService.class)
// 开启配置绑定(使HelloProperties生效)
@EnableConfigurationProperties(HelloProperties.class)
public class HelloAutoConfiguration {
/**
* 注册HelloService Bean
* ConditionalOnMissingBean:容器中无该Bean时才创建,避免覆盖用户自定义Bean
*/
@Bean
@ConditionalOnMissingBean
public HelloService helloService(HelloProperties helloProperties) {
return new HelloService(helloProperties);
}
}
常用条件注解小结: - @ConditionalOnClass:类路径存在指定类时生效 - @ConditionalOnMissingBean:容器无指定Bean时生效 - @ConditionalOnProperty:配置文件存在指定属性时生效 - @ConditionalOnWebApplication:Web环境下生效
Step5:注册自动配置类(SPI核心)
SpringBoot启动时会扫描该文件,加载自动配置类。
- 在resources目录下创建目录:META-INF/spring
- 新建文件:org.springframework.boot.autoconfigure.AutoConfiguration.imports
- 文件内容:写入自动配置类的全限定类名
com.example.hello.config.HelloAutoConfiguration
低版本兼容(SpringBoot 2.7以下):创建META-INF/spring.factories,内容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.hello.config.HelloAutoConfiguration
Step6:打包并安装到本地仓库
执行Maven命令,将Starter打包为jar并安装到本地Maven仓库,供其他项目引入:
# 清理、打包、安装 mvn clean install
安装成功后,可在本地Maven仓库找到com.example/hello-spring-boot-starter/1.0.0目录。
四、测试:引入自定义Starter
Step1:新建SpringBoot Web项目
在新项目的pom.xml中引入自定义Starter依赖:
<!-- 引入自定义Starter -->
<dependency>
<groupId>com.example</groupId>
<artifactId>hello-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
Step2:配置自定义参数(可选)
在application.yml中修改默认配置,不配置则使用默认值:
hello: prefix: 你好 suffix: ~
Step3:编写测试接口
package com.example.test.controller;
import com.example.hello.service.HelloService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class HelloController {
// 直接注入Starter提供的Bean
@Resource
private HelloService helloService;
@GetMapping("/hello/{name}")
public String hello(@PathVariable String name) {
return helloService.sayHello(name);
}
}
Step4:启动测试
启动SpringBoot项目,访问接口:http://localhost:8080/hello/张三,返回结果:你好 张三~,说明Starter生效。
五、进阶优化技巧
- 配置元数据:依赖spring-boot-configuration-processor后,打包会自动生成spring-configuration-metadata.json,IDE会提示配置项
- 开关控制:添加@ConditionalOnProperty(prefix = "hello", name = "enable", havingValue = "true"),实现按需开启Starter
- 依赖隔离:将非核心依赖设为<optional>true</optional>,避免传递不必要的依赖
- 多环境适配:结合@Profile注解,实现不同环境的差异化配置
六、常见避坑点
- 自动配置类的包路径与启动类包路径不一致时,无需手动扫描,SPI机制会自动加载
- 切勿在Starter中添加@SpringBootApplication启动类,否则会导致冲突
- 配置绑定类必须添加get/set方法,否则无法注入配置值
- SpringBoot 3.x需使用Jakarta注解,替换javax包
ps:如果这篇帖子对于还在找工作和找实习的你有所帮助,可以关注我,给本贴点赞、评论、收藏并订阅专栏;同时不要吝啬您的花花
本专栏聚焦Spring全生态体系,从IoC/AOP核心原理入手,覆盖Spring Boot自动配置、事务管理、Web开发等实战内容。拆解循环依赖、动态代理等高频面试难点,助力开发者从入门到精通,打通单体到微服务的技术链路,解决企业级开发痛点,提升架构设计与问题排查能力,成为Java后端进阶的必备技术专栏。