SpringBoot 自动配置原理深度解析:手写自定义 Starter,彻底吃透启动流程

发布时间:2026/6/21 1:27:05
SpringBoot 自动配置原理深度解析:手写自定义 Starter,彻底吃透启动流程 前言SpringBoot 之所以能成为 Java 后端开发的事实标准核心就在于「约定大于配置」的设计理念而自动配置Auto-Configuration正是这一理念的核心载体。很多开发者停留在「引入依赖就能用」的层面对底层的加载流程、SPI 机制、条件注解一知半解既看不懂源码也答不出面试题遇到自定义组件更是无从下手。本文将从注解源码、SPI 机制、条件装配三个维度拆解自动配置原理并手把手带你实现一个自定义 Starter彻底搞懂 SpringBoot 的启动与装配流程。一、自动配置的入口SpringBootApplication 注解拆解我们启动 SpringBoot 项目时都会在启动类上加SpringBootApplication注解它是自动配置的总入口本质上是一个复合注解由三个核心注解组成SpringBootConfigurationEnableAutoConfigurationComponentScan(excludeFilters { … })public interface SpringBootApplication {// …}SpringBootConfiguration本质就是Configuration标记启动类本身是一个 Spring 配置类支持通过Bean注解向容器中注册组件。ComponentScan包扫描注解默认扫描启动类所在包及其子包下所有标注了Component、Service、Controller等注解的类将其加载到 Spring 容器中。这也是为什么我们的业务代码要放在启动类同级目录下的原因。EnableAutoConfiguration自动配置的核心这是真正开启自动配置的注解它通过Import注解导入了AutoConfigurationImportSelector类该类负责加载所有自动配置类。Target(ElementType.TYPE)Retention(RetentionPolicy.RUNTIME)DocumentedInheritedAutoConfigurationPackageImport(AutoConfigurationImportSelector.class)public interface EnableAutoConfiguration {// …}二、自动配置的底层核心Spring SPI 机制AutoConfigurationImportSelector的核心方法是selectImports()它会读取项目中所有META-INF/spring.factories文件找到 key 为org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的所有自动配置类全限定名将其加载到 Spring 容器中。这就是 Spring 的 SPIService Provider Interface机制约定配置文件路径启动时统一扫描加载实现组件的可插拔。SpringBoot 官方提供的所有 Starter比如 spring-boot-starter-web、spring-boot-starter-redis都是通过这种方式注入自动配置类。以 Redis 自动配置为例spring-boot-autoconfigure 包下的 spring.factories 文件中就配置了 RedisAutoConfigurationpropertiesorg.springframework.boot.autoconfigure.EnableAutoConfigurationorg.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration三、自动配置的生效控制Conditional 条件注解并不是所有加载到的自动配置类都会生效SpringBoot 通过一系列Conditional条件注解根据当前环境动态判断是否实例化该配置类。常用的条件注解ConditionalOnClass类路径下存在指定类时配置生效ConditionalOnMissingBean容器中不存在指定 Bean 时配置生效ConditionalOnProperty配置文件中存在指定属性且值匹配时配置生效ConditionalOnWebApplication当前是 Web 应用时配置生效以 Redis 自动配置类为例Configuration(proxyBeanMethods false)ConditionalOnClass(RedisOperations.class) // 类路径有RedisOperations才生效EnableConfigurationProperties(RedisProperties.class) // 绑定配置属性Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })public class RedisAutoConfiguration {BeanConditionalOnMissingBean(name “redisTemplate”) // 容器没有redisTemplate才创建public RedisTemplateObject, Object redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplateObject, Object template new RedisTemplate();template.setConnectionFactory(redisConnectionFactory);return template;}}这就是为什么我们引入 redis starter 后SpringBoot 会自动帮我们创建 RedisTemplate如果我们自己定义了 RedisTemplate默认的就不会生效完美实现了「默认配置 自定义扩展」。四、实战手写一个自定义 SpringBoot Starter理解了原理我们手写一个简单的「字符串脱敏工具 Starter」实现引入依赖即可使用支持配置文件自定义脱敏规则。步骤 1创建 Maven 项目引入核心依赖xmlorg.springframework.bootspring-boot-autoconfigure2.7.18org.springframework.boot spring-boot-configuration-processor 2.7.18 true步骤 2编写属性配置类 绑定配置文件中sensitive.desensitize前缀的配置 ConfigurationProperties(prefix sensitive.desensitize) public class DesensitizeProperties { /** * 是否开启脱敏 */ private boolean enable true; /** * 手机号脱敏保留前几位 */ private int phonePrefixLen 3; /** * 手机号脱敏保留后几位 */ private int phoneSuffixLen 4;// getter、setter方法省略}步骤 3编写核心服务类实现具体的脱敏逻辑public class DesensitizeUtil {private final DesensitizeProperties properties; public DesensitizeUtil(DesensitizeProperties properties) { this.properties properties; } /** * 手机号脱敏 */ public String desensitizePhone(String phone) { if (!properties.isEnable() || phone null || phone.length() 7) { return phone; } int prefixLen properties.getPhonePrefixLen(); int suffixLen properties.getPhoneSuffixLen(); String prefix phone.substring(0, prefixLen); String suffix phone.substring(phone.length() - suffixLen); return prefix **** suffix; }}步骤 4编写自动配置类ConfigurationConditionalOnClass(DesensitizeUtil.class)EnableConfigurationProperties(DesensitizeProperties.class)ConditionalOnProperty(prefix “sensitive.desensitize”, name “enable”, havingValue “true”, matchIfMissing true)public class DesensitizeAutoConfiguration {Bean ConditionalOnMissingBean public DesensitizeUtil desensitizeUtil(DesensitizeProperties properties) { return new DesensitizeUtil(properties); }}步骤 5配置 SPI 文件在 resources 目录下创建META-INF/spring.factories注册自动配置类propertiesorg.springframework.boot.autoconfigure.EnableAutoConfigurationcom.example.desensitize.autoconfigure.DesensitizeAutoConfiguration步骤 6打包并测试将项目 install 到本地仓库在其他 SpringBoot 项目中引入依赖xmlcom.exampledesensitize-spring-boot-starter1.0.0直接注入使用即可RestControllerpublic class TestController {Autowired private DesensitizeUtil desensitizeUtil; GetMapping(/test) public String test() { return desensitizeUtil.desensitizePhone(13812345678); // 输出138****5678 }}五、面试高频考点汇总SpringBoot 自动配置的原理是什么SpringBootApplication 注解由哪些注解组成分别有什么作用spring.factories 文件的作用是什么SPI 机制的原理Conditional 系列常用注解有哪些Starter 的工作原理如何自定义一个 StarterSpringBoot 启动流程是怎样的总结自动配置是 SpringBoot 的灵魂本质上就是「SPI 扫描加载 条件注解动态装配」的组合。理解了自动配置原理不仅能轻松应对面试更能在实际开发中自定义 Starter封装通用组件提升团队开发效率。建议大家结合源码断点调试完整走一遍自动配置加载流程理解会更加深刻。