自动配置原理:@SpringBootApplication 拆开看
为什么加个 spring-boot-starter-web,Tomcat 就自动起来了?为什么连数据库都不配就能连 H2?这一节把这个魔法拆开给你看——它一点都不神秘,就是一堆"如果类路径有 X,就自动配 Y"的条件判断。
论@SpringBootApplication 的三件套
① @Configuration:告诉 Spring 这是一个配置类,里面可以写 @Bean 方法。
② @ComponentScan:扫描当前包及子包,把 @Component/@Service/@RestController 这些注解的类收编为 Bean。
③ @EnableAutoConfiguration:核心中的核心。它会去读所有 jar 包里 META-INF/spring/...AutoConfiguration.imports 文件,把里面列的自动配置类加载进来。
自动配置类长什么样(以 DispatcherServlet 为例)
启动时加参数 --debug,Spring Boot 会打印一份条件评估报告:哪些自动配置类匹配了(positive matches)、哪些没匹配(negative matches)。排查"为什么我的 Bean 没生效"时,先看这份报告。
自定义 Starter:把自动配置封装成自己的轮子
当你团队里有一套通用配置(比如统一的日志格式、统一的异常处理、统一的监控上报),别让每个项目复制粘贴——把它做成一个 starter,别的项目引入依赖就自动生效。结构很简单:一个自动配置类 + 一个 imports 文件。
@ConditionalOnMissingBean:你配了就用你的
这是 Spring Boot 自动配置的核心套路:如果你自己没定义某个 Bean,它就给你配一个默认的;如果你自己定义了,它就闭嘴用你的。这就是"覆盖默认配置"的原理。
自定义 starter 三步
@Conditional 全家桶:四个最常用的条件注解
自动配置的精髓全在 @Conditional 家族。下面四个是高频中的高频,看懂它们,你就看懂了 Boot 一半的魔法。
| 条件注解 | 大白话:满足什么条件才装配这个 Bean |
|---|---|
@ConditionalOnClass(X.class) | 类路径下能找到类 X,才装配。加了 starter 才有这个类,没加就跳过。 |
@ConditionalOnMissingBean | 容器里还没有同类型 Bean,才装默认的。你自己配了就用你的。 |
@ConditionalOnProperty(prefix="x", name="y", havingValue="true") | 配置文件里 x.y=true 才装配。常用于开关某个功能。 |
@ConditionalOnWebApplication | 这是个 Web 应用(有 Servlet 环境)才装 MVC 相关 Bean。 |
实战:写一个带开关的自定义 HTTP 客户端 starter
导入自动配置类的幕后:AutoConfigurationImportSelector
上面说"@EnableAutoConfiguration 去读 imports 文件",背后干这个活的是一个叫 AutoConfigurationImportSelector 的类。它实现了 Spring 的 ImportSelector 接口,把一堆配置类的全限定名告诉容器。知道这条链路,面试就能答出完整原理。
| Boot 版本 | 自动配置类登记在哪 |
|---|---|
| Boot 2.x | 所有 jar 的 META-INF/spring.factories 文件里,用一个 org.springframework.boot.autoconfigure.EnableAutoConfiguration key,把所有自动配置类名写在一行逗号分隔。缺点:启动要解析整个文件,慢。 |
| Boot 3.x | 改成 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,一行一个配置类,加载更快、更清晰。新项目按这个写。 |
论一句话串起整条链路
@SpringBootApplication → @EnableAutoConfiguration → 通过 AutoConfigurationImportSelector 读取所有 jar 的 AutoConfiguration.imports(Boot 2.x 是 spring.factories)→ 加载这些配置类 → 每个类上的 @ConditionalOnXxx 条件不满足就跳过 → 满足的才注册 Bean。这就是"约定优于配置"的全部秘密。
1.(必考题)说说 Spring Boot 自动配置的完整原理。
查看答案
答案:三层:① @SpringBootApplication 包含 @EnableAutoConfiguration;② @EnableAutoConfiguration 去读所有 jar 包 META-INF/spring/...AutoConfiguration.imports 文件,加载列出的自动配置类;③ 每个自动配置类都带 @ConditionalOnXxx,满足条件才注册 Bean。解析:这是标准答案,能讲出"imports 文件 + 条件注解"两个关键词,面试官就知道你真懂。
2.(理解题)@ConditionalOnMissingBean 为什么能实现"你配了就用你的"?
查看答案
答案:自动配置类是在你自己写的 @Bean 之后处理的。它注册 Bean 之前先检查容器里有没有同类型 Bean——有就跳过,没有才注册默认的。解析:这就是为什么"覆盖 Boot 默认配置只要自己定义一个同类型 Bean"。
3.(排错题)我写了个 @Bean 想覆盖 Boot 的默认 DataSource,但没生效。可能什么原因?
查看答案
答案:常见原因:① 你的 @Bean 所在的配置类没被扫描到;② 自动配置优先级问题,顺序不对;③ Bean 类型对不上。解析:加 --debug 看条件评估报告,确认你的 Bean 和默认 Bean 是不是同类型、你的配置类有没有进容器。