news 2026/6/21 1:26:21

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot 自动配置原理深度解析:手写自定义 Starter,彻底吃透启动流程

前言
SpringBoot 之所以能成为 Java 后端开发的事实标准,核心就在于「约定大于配置」的设计理念,而自动配置(Auto-Configuration)正是这一理念的核心载体。很多开发者停留在「引入依赖就能用」的层面,对底层的加载流程、SPI 机制、条件注解一知半解,既看不懂源码,也答不出面试题,遇到自定义组件更是无从下手。
本文将从注解源码、SPI 机制、条件装配三个维度拆解自动配置原理,并手把手带你实现一个自定义 Starter,彻底搞懂 SpringBoot 的启动与装配流程。
一、自动配置的入口:@SpringBootApplication 注解拆解
我们启动 SpringBoot 项目时,都会在启动类上加@SpringBootApplication注解,它是自动配置的总入口,本质上是一个复合注解,由三个核心注解组成:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { … })
public @interface SpringBootApplication {
// …
}

  1. @SpringBootConfiguration
    本质就是@Configuration,标记启动类本身是一个 Spring 配置类,支持通过@Bean注解向容器中注册组件。

  2. @ComponentScan
    包扫描注解,默认扫描启动类所在包及其子包下所有标注了@Component、@Service、@Controller等注解的类,将其加载到 Spring 容器中。这也是为什么我们的业务代码要放在启动类同级目录下的原因。

  3. @EnableAutoConfiguration:自动配置的核心
    这是真正开启自动配置的注解,它通过@Import注解导入了AutoConfigurationImportSelector类,该类负责加载所有自动配置类。
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
    // …
    }
    二、自动配置的底层核心:Spring SPI 机制
    AutoConfigurationImportSelector的核心方法是selectImports(),它会读取项目中所有META-INF/spring.factories文件,找到 key 为org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的所有自动配置类全限定名,将其加载到 Spring 容器中。
    这就是 Spring 的 SPI(Service Provider Interface)机制:约定配置文件路径,启动时统一扫描加载,实现组件的可插拔。SpringBoot 官方提供的所有 Starter(比如 spring-boot-starter-web、spring-boot-starter-redis),都是通过这种方式注入自动配置类。
    以 Redis 自动配置为例,spring-boot-autoconfigure 包下的 spring.factories 文件中,就配置了 RedisAutoConfiguration:
    properties
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=
    org.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 {

    @Bean
    @ConditionalOnMissingBean(name = “redisTemplate”) // 容器没有redisTemplate才创建
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    return template;
    }
    }
    这就是为什么我们引入 redis starter 后,SpringBoot 会自动帮我们创建 RedisTemplate;如果我们自己定义了 RedisTemplate,默认的就不会生效,完美实现了「默认配置 + 自定义扩展」。
    四、实战:手写一个自定义 SpringBoot Starter
    理解了原理,我们手写一个简单的「字符串脱敏工具 Starter」,实现引入依赖即可使用,支持配置文件自定义脱敏规则。
    步骤 1:创建 Maven 项目,引入核心依赖
    xml


    org.springframework.boot
    spring-boot-autoconfigure
    2.7.18

    org.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:编写自动配置类
@Configuration
@ConditionalOnClass(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,注册自动配置类:
properties
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.example.desensitize.autoconfigure.DesensitizeAutoConfiguration
步骤 6:打包并测试
将项目 install 到本地仓库,在其他 SpringBoot 项目中引入依赖:
xml

com.example
desensitize-spring-boot-starter
1.0.0

直接注入使用即可:
@RestController
public class TestController {

@Autowired private DesensitizeUtil desensitizeUtil; @GetMapping("/test") public String test() { return desensitizeUtil.desensitizePhone("13812345678"); // 输出:138****5678 }

}
五、面试高频考点汇总
SpringBoot 自动配置的原理是什么?
@SpringBootApplication 注解由哪些注解组成?分别有什么作用?
spring.factories 文件的作用是什么?SPI 机制的原理?
@Conditional 系列常用注解有哪些?
Starter 的工作原理?如何自定义一个 Starter?
SpringBoot 启动流程是怎样的?
总结
自动配置是 SpringBoot 的灵魂,本质上就是「SPI 扫描加载 + 条件注解动态装配」的组合。理解了自动配置原理,不仅能轻松应对面试,更能在实际开发中自定义 Starter,封装通用组件,提升团队开发效率。建议大家结合源码断点调试,完整走一遍自动配置加载流程,理解会更加深刻。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/21 1:24:44

三亚氛围感餐厅哪家实力强

最近被朋友疯狂安利了一家三亚的神仙餐厅——巴伐利亚魔法餐厅。我本来以为是那种“网红滤镜”大于实际体验的店&#xff0c;结果去了一次&#xff0c;直接原地圈粉&#xff01;今天必须把这家宝藏餐厅安利给所有来三亚旅游、或者本地想找氛围感餐厅的小伙伴。&#x1f52e; 推…

作者头像 李华
网站建设 2026/6/21 1:17:47

卡梅德生物科普IL4(白细胞介素4):免疫平衡的关键调控靶

在免疫生物学研究与生物技术开发中&#xff0c;细胞因子作为细胞间通讯的“信使”&#xff0c;在调控免疫应答、维持机体稳态中发挥着核心作用。白细胞介素4&#xff08;IL4&#xff09;是介导体液免疫与过敏性炎症反应的关键分子&#xff0c;不仅决定了适应性免疫的分化方向&a…

作者头像 李华
网站建设 2026/6/21 1:13:51

OpenClaw:本地AI工作流的可编程调度中枢

1. OpenClaw不是“另一个前端界面”&#xff0c;而是本地AI工作流的中枢调度器很多人第一次看到 OpenClaw&#xff0c;下意识会把它当成 ComfyUI 或 Ollama Web UI 那类图形化前端——点几下就能调模型、聊聊天。我最初也这么想&#xff0c;直到在 Ubuntu 24.04.4 的移动硬盘虚…

作者头像 李华
网站建设 2026/6/21 1:10:47

BEV Occupancy Track:自动驾驶稠密场景感知新范式

1. 项目概述&#xff1a;为什么“2024.2 BEV Occupancy Track”突然成了自动驾驶圈的高频词&#xff1f;如果你最近刷过CVPR、ICRA或Waymo/小马智行的技术博客&#xff0c;大概率已经见过这个组合&#xff1a;BEV Occupancy Track。它不是某个新发布的开源模型名字&#xff0…

作者头像 李华
网站建设 2026/6/21 1:09:50

BurpSuite专业版安装配置全攻略:从Java环境到HTTPS抓包

1. 项目概述&#xff1a;为什么需要一个“全网最详细”的BurpSuite安装教程&#xff1f;如果你是一名网络安全爱好者、渗透测试新手&#xff0c;或者正在学习Web应用安全&#xff0c;那么BurpSuite这个名字对你来说一定如雷贯耳。它被公认为Web安全测试领域的“瑞士军刀”&…

作者头像 李华