当前位置: 首页 > news >正文

SpringBoot 自动配置原理

SpringBoot 自动配置原理

当我们需要用到Redis时,在pom.xml文件加了spring-boot-starter-data-redis依赖,在application.yml里写了几行 Redis 的配置,直接注入StringRedisTemplate就能用。不用手动创建连接工厂,也不用配置序列化器。这些"不用我们操心"的配置,到底是怎么出现的?Spring Boot 怎么知道我们的项目需要哪些 Bean,又怎么决定用什么参数来创建它们?

目录

  • SpringBoot自动装配
  • 自动配置的加载机制
  • 条件装配:不是所有配置都会生效
  • 一个具体例子:HttpMessageConverter
  • 和手动配置的对比
  • 小结

SpringBoot自动装配

Spring Boot 的自动配置,本质上就是在启动时扫描一堆"配置类",根据当前项目的依赖和环境条件,决定哪些配置类该生效、哪些该跳过。

一切的起点是@SpringBootApplication注解。它不只是一个"启动注解"。把它展开是长这样:

@SpringBootApplication// 等价于以下三个注解的组合@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan

三个注解各管各的:

注解职责
@SpringBootConfiguration标记这是一个配置类(本质就是@Configuration
@ComponentScan扫描当前包及子包下的@Component@Service@Controller
@EnableAutoConfiguration开启自动配置,这是今天的主角

@ComponentScan负责把你手动写的 Bean 扫描进来,而@EnableAutoConfiguration负责把 Spring Boot 预定义的配置类加载进来。两者互不干涉,各干各的活。

自动配置的加载机制

@EnableAutoConfiguration是怎么找到那些配置类的?答案在注解的实现里。

打开@EnableAutoConfiguration的源码,我们会看到这么一行:

@Import(AutoConfigurationImportSelector.class)

@Import是 Spring 提供的注解,作用是把指定的类导入到 Spring 容器中。这里导入的是AutoConfigurationImportSelector,它是自动配置的核心调度员。

AutoConfigurationImportSelector做了一件关键的事:去读一个叫META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports的文件(Spring Boot 3.x),或者META-INF/spring.factories(Spring Boot 2.x)。这个文件里列了一大堆配置类的全限定名。

加载流程可以用一张图概括:

这些配置类从哪来呢?答案是starter。当你引入spring-boot-starter-web时,这个 starter 的 jar 包里就包含了对应的自动配置类。Starter 不只是"引入依赖",它还带来了配置逻辑。

条件装配

自动配置类被加载后,不会全部生效。Spring Boot 用了一套条件注解来控制"这个配置类到底要不要生效"。这套机制叫条件装配(Conditional Assembly)

核心注解有这几个:

注解含义例子
@ConditionalOnClassclasspath 中存在某个类时才生效DataSource类才配置数据源
@ConditionalOnMissingBean容器中没有某个 Bean 时才生效你自己没配DataSource,Spring Boot 才帮你配
@ConditionalOnProperty配置文件中有某个属性时才生效spring.redis.host存在才配置 Redis
@ConditionalOnMissingClassclasspath 中不存在某个类时才生效没有某个类才走这个分支

@ConditionalOnMissingBean是最关键的一个。它保证了一件事:如果你自己手动配了一个 Bean,Spring Boot 就不会再帮你配了。你手动配置的优先级永远高于自动配置。这就是"约定优于配置"的具体体现,Spring Boot 给你一个默认值,但你随时可以覆盖。

举个例子:

@Configuration@ConditionalOnClass(DataSource.class)// classpath 里有 DataSource 类才生效publicclassDataSourceAutoConfiguration{@Bean@ConditionalOnMissingBean// 容器里没有 DataSource Bean 才创建publicDataSourcedataSource(){// 用配置文件里的属性创建默认数据源returnnewHikariDataSource(...);}}

这段逻辑的意思是:如果项目里引入了数据库驱动(DataSource.class存在),而且你没有自己手动配DataSourceBean,那 Spring Boot 就用默认参数帮你创建一个 HikariCP 连接池。

但如果你在自己的@Configuration类里写了一个@Bean DataSource,Spring Boot 的这个自动配置就会被跳过。你的手动配置优先。

一个具体例子:HttpMessageConverter

来看一个你每天都在用、但可能没注意过的自动配置。

当开发者写@RequestBody接收 JSON 时,Spring Boot 需要把 JSON 字符串转成 Java 对象。这个转换靠的是HttpMessageConverter。我们从来没有手动注册过MappingJackson2HttpMessageConverter,但它就在容器里了。

因为JacksonAutoConfiguration帮我们做了注册。展开来看:

@AutoConfiguration@ConditionalOnClass(ObjectMapper.class)// classpath 里有 Jackson 才生效publicclassJacksonAutoConfiguration{@Bean@ConditionalOnMissingBean// 没自己配 ObjectMapper 才创建publicObjectMapperjacksonObjectMapper(){returnnewObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);}}

这个配置类的生效条件是:classpath 中存在ObjectMapper.class(也就是你引入了 Jackson 依赖)。当你引入了spring-boot-starter-web,Jackson 作为传递依赖被拉进来,ObjectMapper.class就在 classpath 中了。于是这个配置类生效,帮你创建了一个默认的ObjectMapperBean。

如果你想自定义 ObjectMapper 的行为(比如日期格式、空值策略),只需要自己写一个@Bean ObjectMapper,Spring Boot 的自动配置就会让位。不需要去改任何 Spring Boot 的代码。

和手动配置的对比

既然自动配置这么方便,我们还需要手动写@Configuration吗?

对比维度自动配置手动配置
谁写的Spring Boot / Starter 作者开发者自己
生效条件有依赖 + 没被覆盖 → 自动生效写了就生效
优先级低(有@ConditionalOnMissingBean高(手动配置会覆盖自动配置)
适用场景通用默认配置个性化需求、业务特有配置
可控性黑盒,只能通过配置文件调参数白盒,完全开发者控制

自动配置解决的是"80% 的通用场景",手动配置解决的是"20% 的个性化需求"。两者不矛盾,而是配合关系。Spring Boot 给的是一个能跑的默认值,开发者根据业务需要去覆盖它。

最理想的状态是:项目里几乎不写@Configuration,大部分配置靠 starter + yml 搞定。只有遇到 starter 覆盖不了的场景(比如多数据源、自定义序列化、特殊的 Bean 初始化逻辑),才手动写配置类。

小结

Spring Boot 自动配置机制可以概括为:启动时读取 starter 提供的配置类清单,逐一检查其条件注解;满足条件的配置会被注册到容器中,而用户手动定义的 Bean 则会优先覆盖自动配置。本质上,它就是一份配置类列表 + 一套条件判断机制。当你引入某个依赖后,SpringBoot会识别对应的自动配置类;如果条件满足,就自动创建相关 Bean;如果用户没有显式配置,则使用框架提供的默认配置。

http://www.gsyq.cn/news/1617942.html

相关文章:

  • 死磕信号量实现读者-写者:我被自己写的代码坑惨了
  • Xinference开源大模型本地部署实战指南
  • UABEA:重新定义Unity资源编辑的跨平台革命
  • 大厂高频面试题:手机号加密存储后,如何快速按尾号查询?
  • 终极Windows驱动管理指南:DriverStoreExplorer免费释放C盘空间
  • 为了防止题目链接失效,将题目原文复制如下:
  • Java实现Navicat密码加密解密:AES-256-CBC本地安全存储实战
  • QuickVina 2深度解析:20倍加速的分子对接性能揭秘
  • Go 进阶必修:90% 的人都没用对的“表驱动法”
  • 关于动态规划【力扣300.最长递增子序列的思考】
  • 华为MetaERP Oracle EBS R12 AP 供应商主数据完整配置指南(架构师实施版)一、前置基础配置(必须先完成,否则供应商无法正常使用)(一)财务选项 Financials Opti
  • 给制造以光,让智造有根:中策橡胶卓越智能工厂背后的F5G-A全光力量
  • 基于树莓派的边缘计算安全网关设计与实现
  • 2026燃油车底盘整备调校,选对修理厂事半功倍
  • 5分钟学会免费音乐解锁:打破平台限制的完整指南
  • Walmart SDE Interview Experience 三轮 VO 高频面经 | System Design + BQ + 算法 稳稳拿 Offer(2026)
  • 【第 9 篇:本地化部署——从 0 到 1 的企业级系统部署全记录】
  • 导师严选!盘点2026年备受推崇的的AI智能降重工具
  • Linux基础文件与目录命令实操实验报告
  • FPG财盛国际:围绕服务体系与外汇用户支持体系的路径解读
  • 零API费用的金融AI技能库:104个场景纯Python实现,毫秒级响应
  • DVWA 靶场 SQL 注入实战心得:从手工检测到布尔盲注自动化利用全流程详解
  • 2026广州高端宣传片拍摄团队怎么选?广州AIGC企业视频制作机构盘点
  • 还在手敲数据库三线表?这个SQL自动生成法,建议直接收藏!
  • 三台迷你主机硬跑70B大模型!场面十分尴尬
  • AI Agent 工程师面试题 200 题(codex出品)
  • THPX信号源:把合规意识做到位——细节分析与提示整理
  • 《小程序网站翻译:全球化征程中的关键一环》
  • 802.1X 认证技术指南
  • 第一次学 Neo4j,我终于明白 Agent 为什么不只用 MySQL