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

SpringBoot核心原理深度剖析:自动配置是如何实现的?

SpringBoot核心原理深度剖析:自动配置是如何实现的?

    • 前言
    • 一、什么是自动配置?
    • 二、自动配置的入口:`@SpringBootApplication`
    • 三、`@EnableAutoConfiguration` 做了什么?
    • 四、`AutoConfigurationImportSelector` 核心流程
    • 五、`getAutoConfigurationEntry` 核心逻辑
    • 六、从哪里加载候选配置类?
    • 七、自动配置的核心:条件注解
    • 八、完整流程图
    • 九、实战:手写一个自定义 Starter
    • 十、常见问题与总结
      • Q1:自动配置类什么时候不生效?
      • Q2:如何查看当前哪些自动配置生效?
      • Q3:如何覆盖自动配置?
    • 总结

🌺The Begin🌺点点关注,收藏不迷路🌺

⬇ ⬇ 底部 ⬇ ⬇

前言

用过 SpringBoot 的同学都知道,它最大的特点就是“约定大于配置”。我们只需要引入一个starter,几乎不用写任何配置,就能直接使用 Redis、MongoDB、JDBC、RabbitMQ 等各种中间件。这一切的背后,正是 SpringBoot 的自动配置机制。

那么问题来了:SpringBoot 到底是怎么做到自动配置的?它的底层原理是什么?

今天这篇文章,我会带大家手撕源码 + 流程图 + 案例,彻底搞懂 SpringBoot 自动配置的底层实现。


一、什么是自动配置?

简单说:自动配置 = 根据类路径下的依赖 + 配置文件条件,自动创建并注册对应的 Bean。

比如:

  • 引入spring-boot-starter-data-redis→ 自动创建RedisTemplate
  • 引入spring-boot-starter-web→ 自动配置DispatcherServletTomcatJackson

不需要@EnableXXX,不需要手动写@Bean


二、自动配置的入口:@SpringBootApplication

我们知道,启动类上都会加这个注解:

@SpringBootApplicationpublicclassDemoApplication{publicstaticvoidmain(String[]args){SpringApplication.run(DemoApplication.class,args);}}

点进去看源码:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@SpringBootConfiguration@EnableAutoConfiguration// 关键!@ComponentScanpublic@interfaceSpringBootApplication{}

核心就是@EnableAutoConfiguration


三、@EnableAutoConfiguration做了什么?

再点进去:

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)// 关键!public@interfaceEnableAutoConfiguration{}

这里通过@Import引入了AutoConfigurationImportSelector,它是自动配置的真正实现者


四、AutoConfigurationImportSelector核心流程

AutoConfigurationImportSelector实现了ImportSelector接口,其核心方法是:

@OverridepublicString[]selectImports(AnnotationMetadataannotationMetadata){// 判断是否开启自动配置if(!isEnabled(annotationMetadata)){returnNO_IMPORTS;}// 获取所有自动配置类的全限定名AutoConfigurationEntryautoConfigurationEntry=getAutoConfigurationEntry(annotationMetadata);returnStringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}

五、getAutoConfigurationEntry核心逻辑

这个方法做了几件事:

  1. 获取@EnableAutoConfiguration的排除项(exclude)
  2. META-INF/spring.factoriesMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中加载候选配置类
  3. 过滤掉排除项
  4. 去重、排序
  5. 返回最终要加载的配置类
protectedAutoConfigurationEntrygetAutoConfigurationEntry(AnnotationMetadataannotationMetadata){// 1. 获取 exclude 列表Set<String>exclusions=getExclusions(annotationMetadata);// 2. 加载所有候选配置类List<String>configurations=getCandidateConfigurations(annotationMetadata);// 3. 移除 exclude 的configurations.removeAll(exclusions);// 4. 过滤(比如条件注解)configurations=filter(configurations);returnnewAutoConfigurationEntry(configurations,exclusions);}

六、从哪里加载候选配置类?

核心方法getCandidateConfigurations

protectedList<String>getCandidateConfigurations(AnnotationMetadatametadata,AnnotationAttributesattributes){List<String>configurations=SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());returnconfigurations;}

loadFactoryNames会扫描所有 jar 包下的META-INF/spring.factories文件,key =EnableAutoConfiguration对应的配置类。

示例(spring-boot-autoconfigure 包中的部分内容):

# 文件:META-INF/spring.factories org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ ...

注意:SpringBoot 2.7 之后部分配置迁移到META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports


七、自动配置的核心:条件注解

自动配置类并不会无条件加载,而是通过@Conditional系列注解控制。

举例:DataSourceAutoConfiguration

@Configuration(proxyBeanMethods=false)@ConditionalOnClass({DataSource.class,EmbeddedDatabaseType.class})@ConditionalOnMissingBean(type="io.r2dbc.spi.ConnectionFactory")@EnableConfigurationProperties(DataSourceProperties.class)@Import(DataSourcePoolMetadataProvidersConfiguration.class)publicclassDataSourceAutoConfiguration{// ...}

常见条件注解:

注解作用
@ConditionalOnClass类路径下存在某类才生效
@ConditionalOnMissingBean容器中无某 Bean 才生效
@ConditionalOnProperty配置文件中存在某属性才生效
@ConditionalOnWebApplication是 Web 环境才生效

这就是为什么你配了spring.datasource.url,自动配置才会创建DataSource


八、完整流程图

+-----------------------------------+ | 启动类 @SpringBootApplication | +-----------------------------------+ | v +-----------------------------------+ | @EnableAutoConfiguration | +-----------------------------------+ | v +-----------------------------------+ | AutoConfigurationImportSelector | +-----------------------------------+ | v +-----------------------------------+ | getAutoConfigurationEntry | | - 获取 exclude | | - 加载 META-INF/spring.factories | | - 过滤 exclude | | - @Conditional 过滤 | +-----------------------------------+ | v +-----------------------------------+ | 加载自动配置类 (如 RedisAutoConf) | +-----------------------------------+ | v +-----------------------------------+ | 条件注解检查 (@ConditionalOnXX) | | - 存在类? | | - 存在配置? | | - 存在 Bean? | +-----------------------------------+ | v +-----------------------------------+ | 创建并注册相应的 Bean 到容器 | +-----------------------------------+

九、实战:手写一个自定义 Starter

  1. 创建自动配置类
@Configuration@ConditionalOnClass(HelloService.class)@EnableConfigurationProperties(HelloProperties.class)publicclassHelloAutoConfiguration{@Bean@ConditionalOnMissingBeanpublicHelloServicehelloService(HelloPropertiesproperties){returnnewHelloService(properties);}}
  1. 编写配置属性类
@ConfigurationProperties(prefix="hello")publicclassHelloProperties{privateStringname="world";privateStringmsg="hello";// getter/setter}
  1. META-INF/spring.factories中注册
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.starter.HelloAutoConfiguration

这样别人引入你的 starter 后,只要配置hello.name=xxxHelloService就会自动注入容器。


十、常见问题与总结

Q1:自动配置类什么时候不生效?

  • 被 exclude 手动排除
  • 条件注解不满足(类不存在 / 属性未配置 / Bean 已存在)

Q2:如何查看当前哪些自动配置生效?

启动时加--debug,可以看到:

Positive matches: DataSourceAutoConfiguration matched Negative matches: RedisAutoConfiguration: missing required class org.springframework.data.redis.core.RedisOperations

Q3:如何覆盖自动配置?

  • 自己定义同名的@Bean
  • 使用spring.autoconfigure.exclude排除
  • 修改配置属性(如spring.datasource.url

总结

SpringBoot 自动配置的本质:

  1. 入口@EnableAutoConfiguration
  2. 加载器AutoConfigurationImportSelector
  3. 配置来源META-INF/spring.factoriesAutoConfiguration.imports
  4. 生效控制@Conditional系列条件注解
  5. 属性绑定@ConfigurationProperties+@EnableConfigurationProperties

理解了这个流程,你就能:

  • 快速定位 Bean 为什么生效 / 不生效
  • 自定义自己的 Starter
  • 看懂 SpringBoot 源码的核心脉络

希望这篇文章能帮你真正搞懂 SpringBoot 自动配置的原理。如果觉得有收获,欢迎点赞 + 收藏 + 评论交流!


🌺The End🌺点点关注,收藏不迷路🌺

⬆ ⬆ 顶部 ⬆ ⬆
http://www.jsqmd.com/news/924701/

相关文章:

  • 解决MDK升级后嵌入式项目构建失败的兼容性问题
  • 终极指南:如何在FUXA中创建生动的工业管道动画效果 [特殊字符]
  • 如何下载视频号的视频?2026全场景合规操作与工具风险解析
  • Gemini自动续费取消≠退款自动触发!3类高危操作清单+2024年最新退款时效承诺白皮书
  • 2026年分切机/分条机/模切机行业优选榜单:电脑分切机、全自动分条机、高速模切机等源头工厂与高精度设备深度解析 - 品牌企业推荐师(官方)
  • 上海除甲醛公司与市场观察:直营与加盟怎么选? - 资讯纵览
  • 如何永久保存你的数字记忆?WeChatMsg留痕项目完整指南
  • 引导流程漏斗崩塌预警,深度拆解Gemini前30秒用户流失的5大技术归因与实时拦截方案
  • 抖音音频批量下载专业指南:3步实现无损音乐自动化采集
  • Arduino记忆游戏开发:从电路设计到状态机编程的嵌入式实践
  • RevokeMsgPatcher:让撤回的消息无处可藏!Windows微信QQ防撤回终极指南
  • 如何永久保存微信聊天记录:WeChatMsg完整导出指南
  • AI如何构建供应链韧性:从智能预测到动态优化的四大落地场景
  • 雀魂MAX终极指南:一键解锁完整角色装扮的完整解决方案
  • 【独家首发】Gemini三大致命短板曝光:基于2176次Benchmark测试的竞对反超路径
  • 如何用VinXiangQi三步搭建终极象棋AI视觉识别系统:从新手到高手的完整指南
  • 北京除甲醛公司优劣评判标准及直营加盟模式深度解析 - 资讯纵览
  • 电子玩具辅助改造:为特殊需求儿童并联大按钮触发电路
  • Linux运维排查:用turbostat揪出服务器耗电异常的元凶(附CentOS 8/7实战命令)
  • 【Gemini精准营销方案权威白皮书】:基于17个行业、214万用户行为数据的AB测试结论
  • 如何快速掌握SVFI:AI视频补帧的完整解决方案
  • 第3章:codex 安装配置与环境准备
  • 3个步骤,如何用WeChatMsg将微信聊天记录转化为你的个人数字资产?
  • 当大模型“说错话”已成常态——Gemini级危机的7层防御体系(含实时语义熔断机制设计图)
  • An Empirical Evaluation of Columnar Storage Formats
  • 给你的Windows系统来一次彻底“瘦身“:Win11Debloat系统优化工具完全指南
  • Gemini与Claude、GPT-4对比实测:12项基准测试数据全公开,新手选型决策树直接套用
  • 终极指南:如何用AI打造你的专属微信智能聊天助手
  • 从达芬奇透视法到Web3生成艺术:技术驱动艺术演进的底层逻辑与实践
  • 具身智能的先锋:物理世界中的机器人如何依赖 Agent 架构