SpringBoot 自动配置原理

发布时间:2026/7/2 1:51:55
SpringBoot 自动配置原理 SpringBoot 自动配置原理当我们需要用到Redis时在pom.xml文件加了spring-boot-starter-data-redis依赖在application.yml里写了几行 Redis 的配置直接注入StringRedisTemplate就能用。不用手动创建连接工厂也不用配置序列化器。这些不用我们操心的配置到底是怎么出现的Spring Boot 怎么知道我们的项目需要哪些 Bean又怎么决定用什么参数来创建它们目录SpringBoot自动装配自动配置的加载机制条件装配不是所有配置都会生效一个具体例子HttpMessageConverter和手动配置的对比小结SpringBoot自动装配Spring Boot 的自动配置本质上就是在启动时扫描一堆配置类根据当前项目的依赖和环境条件决定哪些配置类该生效、哪些该跳过。一切的起点是SpringBootApplication注解。它不只是一个启动注解。把它展开是长这样SpringBootApplication// 等价于以下三个注解的组合SpringBootConfigurationEnableAutoConfigurationComponentScan三个注解各管各的注解职责SpringBootConfiguration标记这是一个配置类本质就是ConfigurationComponentScan扫描当前包及子包下的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.factoriesSpring Boot 2.x。这个文件里列了一大堆配置类的全限定名。加载流程可以用一张图概括这些配置类从哪来呢答案是starter。当你引入spring-boot-starter-web时这个 starter 的 jar 包里就包含了对应的自动配置类。Starter 不只是引入依赖它还带来了配置逻辑。条件装配自动配置类被加载后不会全部生效。Spring Boot 用了一套条件注解来控制这个配置类到底要不要生效。这套机制叫条件装配Conditional Assembly。核心注解有这几个注解含义例子ConditionalOnClassclasspath 中存在某个类时才生效有DataSource类才配置数据源ConditionalOnMissingBean容器中没有某个 Bean 时才生效你自己没配DataSourceSpring Boot 才帮你配ConditionalOnProperty配置文件中有某个属性时才生效spring.redis.host存在才配置 RedisConditionalOnMissingClassclasspath 中不存在某个类时才生效没有某个类才走这个分支ConditionalOnMissingBean是最关键的一个。它保证了一件事如果你自己手动配了一个 BeanSpring Boot 就不会再帮你配了。你手动配置的优先级永远高于自动配置。这就是约定优于配置的具体体现Spring Boot 给你一个默认值但你随时可以覆盖。举个例子ConfigurationConditionalOnClass(DataSource.class)// classpath 里有 DataSource 类才生效publicclassDataSourceAutoConfiguration{BeanConditionalOnMissingBean// 容器里没有 DataSource Bean 才创建publicDataSourcedataSource(){// 用配置文件里的属性创建默认数据源returnnewHikariDataSource(...);}}这段逻辑的意思是如果项目里引入了数据库驱动DataSource.class存在而且你没有自己手动配DataSourceBean那 Spring Boot 就用默认参数帮你创建一个 HikariCP 连接池。但如果你在自己的Configuration类里写了一个Bean DataSourceSpring Boot 的这个自动配置就会被跳过。你的手动配置优先。一个具体例子HttpMessageConverter来看一个你每天都在用、但可能没注意过的自动配置。当开发者写RequestBody接收 JSON 时Spring Boot 需要把 JSON 字符串转成 Java 对象。这个转换靠的是HttpMessageConverter。我们从来没有手动注册过MappingJackson2HttpMessageConverter但它就在容器里了。因为JacksonAutoConfiguration帮我们做了注册。展开来看AutoConfigurationConditionalOnClass(ObjectMapper.class)// classpath 里有 Jackson 才生效publicclassJacksonAutoConfiguration{BeanConditionalOnMissingBean// 没自己配 ObjectMapper 才创建publicObjectMapperjacksonObjectMapper(){returnnewObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);}}这个配置类的生效条件是classpath 中存在ObjectMapper.class也就是你引入了 Jackson 依赖。当你引入了spring-boot-starter-webJackson 作为传递依赖被拉进来ObjectMapper.class就在 classpath 中了。于是这个配置类生效帮你创建了一个默认的ObjectMapperBean。如果你想自定义 ObjectMapper 的行为比如日期格式、空值策略只需要自己写一个Bean ObjectMapperSpring Boot 的自动配置就会让位。不需要去改任何 Spring Boot 的代码。和手动配置的对比既然自动配置这么方便我们还需要手动写Configuration吗对比维度自动配置手动配置谁写的Spring Boot / Starter 作者开发者自己生效条件有依赖 没被覆盖 → 自动生效写了就生效优先级低有ConditionalOnMissingBean高手动配置会覆盖自动配置适用场景通用默认配置个性化需求、业务特有配置可控性黑盒只能通过配置文件调参数白盒完全开发者控制自动配置解决的是80% 的通用场景手动配置解决的是20% 的个性化需求。两者不矛盾而是配合关系。Spring Boot 给的是一个能跑的默认值开发者根据业务需要去覆盖它。最理想的状态是项目里几乎不写Configuration大部分配置靠 starter yml 搞定。只有遇到 starter 覆盖不了的场景比如多数据源、自定义序列化、特殊的 Bean 初始化逻辑才手动写配置类。小结Spring Boot 自动配置机制可以概括为启动时读取 starter 提供的配置类清单逐一检查其条件注解满足条件的配置会被注册到容器中而用户手动定义的 Bean 则会优先覆盖自动配置。本质上它就是一份配置类列表 一套条件判断机制。当你引入某个依赖后SpringBoot会识别对应的自动配置类如果条件满足就自动创建相关 Bean如果用户没有显式配置则使用框架提供的默认配置。