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

发布时间:2026/5/31 19:23:49

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→ 自动配置DispatcherServlet、Tomcat、Jackson不需要EnableXXX不需要手动写Bean。二、自动配置的入口SpringBootApplication我们知道启动类上都会加这个注解SpringBootApplicationpublicclassDemoApplication{publicstaticvoidmain(String[]args){SpringApplication.run(DemoApplication.class,args);}}点进去看源码Target(ElementType.TYPE)Retention(RetentionPolicy.RUNTIME)DocumentedInheritedSpringBootConfigurationEnableAutoConfiguration// 关键ComponentScanpublicinterfaceSpringBootApplication{}核心就是EnableAutoConfiguration。三、EnableAutoConfiguration做了什么再点进去Target(ElementType.TYPE)Retention(RetentionPolicy.RUNTIME)DocumentedInheritedAutoConfigurationPackageImport(AutoConfigurationImportSelector.class)// 关键publicinterfaceEnableAutoConfiguration{}这里通过Import引入了AutoConfigurationImportSelector它是自动配置的真正实现者。四、AutoConfigurationImportSelector核心流程AutoConfigurationImportSelector实现了ImportSelector接口其核心方法是OverridepublicString[]selectImports(AnnotationMetadataannotationMetadata){// 判断是否开启自动配置if(!isEnabled(annotationMetadata)){returnNO_IMPORTS;}// 获取所有自动配置类的全限定名AutoConfigurationEntryautoConfigurationEntrygetAutoConfigurationEntry(annotationMetadata);returnStringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}五、getAutoConfigurationEntry核心逻辑这个方法做了几件事获取EnableAutoConfiguration的排除项exclude从META-INF/spring.factories或META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中加载候选配置类过滤掉排除项去重、排序返回最终要加载的配置类protectedAutoConfigurationEntrygetAutoConfigurationEntry(AnnotationMetadataannotationMetadata){// 1. 获取 exclude 列表SetStringexclusionsgetExclusions(annotationMetadata);// 2. 加载所有候选配置类ListStringconfigurationsgetCandidateConfigurations(annotationMetadata);// 3. 移除 exclude 的configurations.removeAll(exclusions);// 4. 过滤比如条件注解configurationsfilter(configurations);returnnewAutoConfigurationEntry(configurations,exclusions);}六、从哪里加载候选配置类核心方法getCandidateConfigurationsprotectedListStringgetCandidateConfigurations(AnnotationMetadatametadata,AnnotationAttributesattributes){ListStringconfigurationsSpringFactoriesLoader.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系列注解控制。举例DataSourceAutoConfigurationConfiguration(proxyBeanMethodsfalse)ConditionalOnClass({DataSource.class,EmbeddedDatabaseType.class})ConditionalOnMissingBean(typeio.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创建自动配置类ConfigurationConditionalOnClass(HelloService.class)EnableConfigurationProperties(HelloProperties.class)publicclassHelloAutoConfiguration{BeanConditionalOnMissingBeanpublicHelloServicehelloService(HelloPropertiesproperties){returnnewHelloService(properties);}}编写配置属性类ConfigurationProperties(prefixhello)publicclassHelloProperties{privateStringnameworld;privateStringmsghello;// getter/setter}在META-INF/spring.factories中注册org.springframework.boot.autoconfigure.EnableAutoConfiguration\ com.example.starter.HelloAutoConfiguration这样别人引入你的 starter 后只要配置hello.namexxxHelloService就会自动注入容器。十、常见问题与总结Q1自动配置类什么时候不生效被 exclude 手动排除条件注解不满足类不存在 / 属性未配置 / Bean 已存在Q2如何查看当前哪些自动配置生效启动时加--debug可以看到Positive matches: DataSourceAutoConfiguration matched Negative matches: RedisAutoConfiguration: missing required class org.springframework.data.redis.core.RedisOperationsQ3如何覆盖自动配置自己定义同名的Bean使用spring.autoconfigure.exclude排除修改配置属性如spring.datasource.url总结SpringBoot 自动配置的本质入口EnableAutoConfiguration加载器AutoConfigurationImportSelector配置来源META-INF/spring.factories或AutoConfiguration.imports生效控制Conditional系列条件注解属性绑定ConfigurationPropertiesEnableConfigurationProperties理解了这个流程你就能快速定位 Bean 为什么生效 / 不生效自定义自己的 Starter看懂 SpringBoot 源码的核心脉络希望这篇文章能帮你真正搞懂 SpringBoot 自动配置的原理。如果觉得有收获欢迎点赞 收藏 评论交流The End点点关注收藏不迷路⬆ ⬆ 顶部 ⬆ ⬆

相关新闻