🔥 Spring全家桶源码连载系列(SpringBoot核心篇)

上一篇第14篇,我们搞懂了 SpringBoot 启动流程、约定大于配置、Starter 基础原理。

但所有开发者最大的疑问始终是:

为什么SpringBoot引入一个starter就能自动配置好所有Bean?

自动配置到底是怎么生效的?底层源码链路是什么?

为什么有的组件自动创建,有的不创建?条件注解如何工作?

可以这么说:弄懂了自动配置,才算真正弄懂了SpringBoot

自动配置是 SpringBoot 的灵魂核心,也是面试必问、底层最难、工作最常用的核心知识点。

本篇带大家手撕全套自动配置源码:SPI扩展机制 → 自动配置加载流程 → 条件注解匹配 → Bean动态装配 → 手动覆盖默认配置,全网最透彻、无废话干货解析!

一、自动配置核心前置认知

1.1 什么是SpringBoot自动配置?

定义:SpringBoot 根据项目中引入的 Maven 依赖,自动推断运行环境,在容器启动时自动加载对应的配置类、自动创建通用Bean、自动整合框架环境,无需开发者手动配置。

简单一句话:你引入什么依赖,SpringBoot就帮你自动配好什么环境

1.2 为什么需要自动配置?

回顾 SSM 开发:

  • 使用 SpringMVC 需要手动配置视图解析器、拦截器、参数解析器

  • 使用 MyBatis 需要手动配置 SqlSessionFactory、MapperScanner

  • 使用事务需要手动配置事务管理器、开启事务注解

而 SpringBoot 自动配置,把所有通用模板配置全部预写死在框架内部,项目启动时按需加载,彻底消灭重复配置。

1.3 自动配置的两大核心基石

SpringBoot 自动配置能跑通,完全依赖两大机制:

  1. Java SPI / Spring SPI 扩展机制:找到所有自动配置类

  2. 条件注解机制:判断是否需要创建 Bean、是否生效配置

二、自动配置入口:@EnableAutoConfiguration 深度拆解

我们上篇讲过,@SpringBootApplication 核心包含三大注解,其中 @EnableAutoConfiguration 就是自动配置的开关。

点开注解源码,底层藏着两个关键注解。

2.1 @AutoConfigurationPackage(自动扫描包)

作用:自动扫描启动类所在包及子包,将业务组件(Controller/Service/Component)注册到容器。

这也是为什么 SpringBoot 启动类必须放在根包的原因,否则无法扫描到业务Bean。

2.2 @Import(AutoConfigurationImportSelector.class)(核心灵魂)

这是自动配置的真正入口

通过 @Import 导入 AutoConfigurationImportSelector 选择器类,该类实现了 Spring 的 DeferredImportSelector 接口。

在容器刷新阶段,会自动执行该选择器的核心方法,加载所有自动配置类

三、SPI机制:自动配置类是怎么被找到的?

3.1 什么是SPI?

SPI(Service Provider Interface):服务提供者扩展机制。

核心思想:接口定义规范,配置文件指定实现类,程序动态加载实现类,实现解耦与拓展。

SpringBoot 基于 SPI 思想,实现了自定义 Spring SPI,用来加载海量自动配置类。

3.2 自动配置配置文件位置

在 SpringBoot 源码包中,存在核心配置文件:

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

文件内部,存放了SpringBoot所有内置自动配置类全路径,多达上百个:

  • WebMvcAutoConfiguration(Web环境自动配置)

  • DataSourceAutoConfiguration(数据源自动配置)

  • TransactionAutoConfiguration(事务自动配置)

  • JacksonAutoConfiguration(JSON序列化自动配置)

  • ServletWebServerFactoryAutoConfiguration(内嵌Tomcat自动配置)

3.3 SPI加载流程

  1. 项目启动,触发 AutoConfigurationImportSelector 执行

  2. 通过 SpringFactoriesLoader 加载 resources 下的 imports 配置文件

  3. 读取所有预定义的自动配置类全限定名

  4. 去重、过滤、排序,得到候选自动配置类集合

  5. 将这些配置类导入 Spring 容器,当作配置类解析

核心结论:SpringBoot 启动时,默认加载上百个自动配置类,再通过条件注解筛选是否生效。

四、条件注解:决定配置生不生效的关键(面试必考)

如果所有自动配置类全部生效,会造成大量冗余Bean、冲突Bean。

所以 SpringBoot 设计了条件注解体系满足条件才创建Bean,不满足直接跳过

所有自动配置类,全部基于条件注解实现按需加载。

4.1 核心条件注解大全

  • @ConditionalOnClass:classpath下存在指定类,才生效配置

  • @ConditionalOnMissingClass:classpath下不存在指定类,才生效

  • @ConditionalOnBean:容器中存在指定Bean,才生效

  • @ConditionalOnMissingBean:容器中没有指定Bean,才生效(最常用)

  • @ConditionalOnProperty:配置文件存在指定配置,才生效

  • @ConditionalOnWebApplication:当前是Web环境,才生效

  • @ConditionalOnResource:存在指定资源文件,才生效

4.2 核心原理:按需装配

举个典型例子:WebMvcAutoConfiguration

该配置类上加了 @ConditionalOnWebApplication,只有项目引入web依赖、属于web环境时,才会加载SpringMVC自动配置。

非web项目,直接跳过该配置类,不加载无效Bean。

4.3 @ConditionalOnMissingBean 核心机制(重中之重)

这是 SpringBoot 默认配置与自定义配置优先级 的核心关键!

规则:

  • 如果开发者手动自定义了Bean,容器中已存在该Bean

  • SpringBoot 自带的自动配置Bean 不会创建

  • 如果开发者没有自定义,SpringBoot 自动创建默认Bean

一句话总结:用户优先,框架兜底

这就是为什么我们自定义配置类可以覆盖SpringBoot默认配置的底层原理!

五、完整自动配置执行源码链路(逐步骤吃透)

结合前面学的 IoC 容器刷新流程,串联完整自动配置执行顺序,面试可直接口述满分。

步骤1:启动类标记 @EnableAutoConfiguration

开启自动配置开关,导入 AutoConfigurationImportSelector 选择器。

步骤2:容器刷新阶段执行选择器方法

Spring 容器 refresh() 过程中,处理 @Import 导入的选择器,触发 selectImports() 方法。

步骤3:SPI加载所有自动配置类

读取 META-INF 下的 imports 文件,加载全部自动配置类全限定名,得到候选配置列表。

步骤4:过滤、去重、排除指定配置

根据注解 exclude 属性、配置文件排除配置,剔除不需要加载的自动配置类。

步骤5:将剩余配置类导入容器,当作配置类解析

Spring 将这些自动配置类,和我们自己写的 @Configuration 配置类同等对待

步骤6:解析配置类中的 @Bean 方法

遍历自动配置类,读取内部所有 @Bean 注解方法。

步骤7:条件注解匹配校验

执行每个Bean的条件注解判断,满足条件则创建Bean,不满足直接跳过。

步骤8:自动Bean注册到IoC容器

生效的默认Bean完成实例化、初始化,存入单例池,完成自动装配。

至此,SpringBoot自动配置全过程结束!

六、实战案例:WebMvcAutoConfiguration 源码解析

我们以最常用的Web自动配置类为例,落地验证上述原理。

WebMvcAutoConfiguration 核心功能:自动配置SpringMVC全套环境

  • 自动配置拦截器、转换器、格式化器

  • 自动配置JSON参数解析器、消息转换器

  • 自动配置视图控制器、静态资源映射规则

  • 自动配置跨域、异常基础适配规则

该类严格遵循条件注解规则:仅Web环境生效,且用户未自定义MVC配置时,默认启用框架配置。

当我们手动实现 WebMvcConfigurer 自定义配置时,不会完全覆盖默认配置,而是拓展追加配置,这也是SpringBoot的人性化设计。

七、自动配置核心拓展规则(面试高频坑点)

7.1 自定义配置 & 自动配置优先级

自定义Bean > SpringBoot自动配置Bean

底层依托 @ConditionalOnMissingBean 实现,用户手动定义的Bean优先注册,框架默认Bean失效,完美实现自定义覆盖默认。

7.2 如何关闭指定自动配置?

在启动类注解中排除指定自动配置类:

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

适用于需要手动全权接管数据源、事务等特殊场景。

7.3 自动配置的核心优势总结

  • 零配置开箱即用,极大提升开发效率

  • 按需加载,无冗余Bean,不浪费资源

  • 用户配置优先,拓展性极强

  • 统一框架底层配置规范,避免人为配置错误

八、高频面试真题满分必背

1、SpringBoot自动配置原理?

SpringBoot自动配置基于@EnableAutoConfiguration注解开启,底层通过AutoConfigurationImportSelector结合Spring SPI机制,加载META-INF目录下的所有自动配置类。再通过各类条件注解按需匹配环境,在用户未自定义Bean的情况下,自动创建框架默认Bean,完成全套环境自动装配,实现零配置开发。

2、SPI机制在SpringBoot中的作用?

SPI是SpringBoot自动配置的核心加载机制,通过读取固定配置文件中的自动配置类全路径,批量加载框架预定义的配置类,实现配置类的动态发现与加载,解耦框架与业务,支撑自动装配能力。

3、@ConditionalOnMissingBean的作用?

该条件注解表示仅当容器中不存在对应Bean时,才创建当前Bean。保证开发者自定义的Bean优先级高于框架默认Bean,实现用户配置覆盖框架默认配置,兼顾开箱即用与自定义拓展能力。

4、为什么引入starter就能自动配置?

引入starter后,项目classpath中会出现对应框架依赖类,触发自动配置类的@ConditionalOnClass条件匹配,使对应的自动配置类生效,自动创建相关功能Bean,无需手动配置即可使用对应功能。

5、如何实现SpringBoot自定义starter?

自定义starter需要两步:1、创建自动配置类,通过条件注解定义Bean加载规则;2、在META-INF/imports文件中配置自定义自动配置类路径,项目引入该starter后,即可通过SPI机制自动加载配置,实现自定义场景的自动装配。

九、本篇总结 & 下期预告

本篇总结

本篇彻底击穿 SpringBoot 最核心的自动配置原理,打通底层核心逻辑:

  • 掌握自动配置入口注解与底层核心类

  • 吃透 SPI 扩展机制的加载原理与作用

  • 精通全套条件注解的匹配规则与实战场景

  • 理解用户配置优先、框架兜底的设计思想

  • 完整掌握自动配置从加载、筛选、创建到注册的全流程

至此,你已经彻底搞懂 SpringBoot「零配置」的底层真相!

下期预告

下一篇第十六篇,我们拆解 SpringBoot内嵌Tomcat源码全解!搞懂为什么不用外置Tomcat、内嵌容器启动流程、端口绑定、Web容器初始化底层原理,补齐SpringBoot Web核心最后一块短板!

💡 往期推荐 & 系列连载

本Spring全家桶源码系列循序渐进、层层拆解,吃透底层原理,搞定所有面试与工作疑难!

更多推荐