SpringBoot 自动配置原理
Spring Boot 的自动配置是其“约定优于配置”理念的核心体现,它极大地简化了 Spring 应用的初始搭建和开发过程。其原理主要基于以下几个关键机制协同工作:
-
@SpringBootApplication
注解- 这是 Spring Boot 应用的入口点注解,通常标注在主类上。
- 它是一个组合注解,核心包含:
@SpringBootConfiguration
: 表明这是一个 Spring Boot 配置类(本质上是@Configuration
)。@EnableAutoConfiguration
: 启用自动配置的关键注解。@ComponentScan
: 扫描当前包及其子包下的组件(@Component
,@Service
,@Repository
,@Controller
等)。
-
@EnableAutoConfiguration
注解- 这个注解是自动配置的“开关”。
- 它通过
@Import(AutoConfigurationImportSelector.class)
导入了一个核心类AutoConfigurationImportSelector
。
-
AutoConfigurationImportSelector
- 这个类是自动配置的核心驱动者,实现了
DeferredImportSelector
接口。 - 它的核心方法
selectImports()
负责决定哪些自动配置类应该被加载到 Spring 容器中。 - 加载过程:
- 定位资源: 使用 Spring Framework 的
SpringFactoriesLoader
机制。 - 读取配置: 从 classpath 下
META-INF/spring.factories
文件中加载配置。 - 获取候选类: 查找该文件中
org.springframework.boot.autoconfigure.EnableAutoConfiguration
这个 key 对应的值。这个值是一个逗号分隔的、全限定名的自动配置类列表。例如:org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ ... # 非常长的列表,包含所有内置的自动配置类
- 过滤:
AutoConfigurationImportSelector
会对读取到的候选类列表进行过滤(基于类路径上是否存在必要的类、是否存在特定的 Bean 等条件),最终确定真正需要导入的自动配置类。
- 定位资源: 使用 Spring Framework 的
- 这个类是自动配置的核心驱动者,实现了
-
自动配置类 (
XxxAutoConfiguration
)- 这些就是
spring.factories
文件中列出的类(例如DataSourceAutoConfiguration
,WebMvcAutoConfiguration
,JacksonAutoConfiguration
等)。 - 它们是标准的
@Configuration
配置类。 - 它们内部使用
@Bean
注解来定义各种组件(如 DataSource, RestTemplate, ViewResolver, JacksonObjectMapper
等)。 - 条件化配置: 这是自动配置智能化的关键!这些自动配置类上使用了大量的
@Conditional
及其派生注解来控制配置是否生效以及 Bean 是否被创建。常见的条件注解有:@ConditionalOnClass
: 当 classpath 中存在指定的类时,配置才生效。@ConditionalOnMissingBean
: 当 Spring 容器中不存在指定类型、名称或限定符的 Bean 时,配置才生效(允许用户覆盖默认配置)。@ConditionalOnProperty
: 当指定的配置属性有一个特定的值时,配置才生效。@ConditionalOnWebApplication
/@ConditionalOnNotWebApplication
: 根据是否是 Web 应用决定。@ConditionalOnResource
: 当存在指定的资源文件时,配置才生效。@ConditionalOnJava
: 根据 JVM 版本决定。@ConditionalOnSingleCandidate
: 当容器中存在且只存在一个指定类型的 Bean,或者有多个但有一个是@Primary
时生效。@ConditionalOnExpression
: 基于 SpEL 表达式的复杂条件。
- 配置属性绑定: 自动配置类通常会注入一个以
XxxProperties
命名的类(例如ServerProperties
,DataSourceProperties
)。这个类使用@ConfigurationProperties
注解,将application.properties
或application.yml
中的前缀匹配的属性绑定进来。配置类使用这些属性对象来定制化它们创建的 Bean。
- 这些就是
-
spring-boot-autoconfigure
Jar 包- 这是 Spring Boot 提供的一个核心模块。
- 它包含了大量的内置自动配置类 (
XxxAutoConfiguration
)。 - 它包含了
META-INF/spring.factories
文件,其中列出了所有这些自动配置类。 - 它包含了大量的
XxxProperties
类,用于绑定配置属性。 - Starter 依赖: 当你引入一个 Spring Boot Starter(如
spring-boot-starter-web
,spring-boot-starter-data-jpa
)时,它会传递性地引入spring-boot-starter
(核心功能) 和spring-boot-autoconfigure
,以及该 Starter 所需的其他第三方库。spring-boot-autoconfigure
中的自动配置类感知到这些库的存在(通过@ConditionalOnClass
),就会自动配置相应的功能。
自动配置生效的关键流程总结:
- 启动应用: 执行
SpringApplication.run(...)
。 - 扫描主类: Spring 容器启动,发现主类上的
@SpringBootApplication
。 - 启用自动配置:
@EnableAutoConfiguration
生效。 - 调用 Selector:
AutoConfigurationImportSelector
被触发。 - 加载 Factories: Selector 通过
SpringFactoriesLoader
加载META-INF/spring.factories
中EnableAutoConfiguration
下列出的所有候选自动配置类。 - 过滤条件: Selector 根据 classpath 上的 jar 包(即存在的类)、已有的 Bean 定义、环境变量/配置属性等条件,过滤掉不满足
@Conditional
条件的自动配置类。 - 导入配置: 将过滤后剩余的、真正有效的自动配置类导入 Spring 容器。
- 执行配置: 这些被导入的自动配置类 (
XxxAutoConfiguration
) 本身是@Configuration
类,它们开始执行:- 读取绑定的
XxxProperties
(其值来自application.properties/yml
)。 - 检查各种
@Conditional
条件(通常是@ConditionalOnClass
,@ConditionalOnMissingBean
)。 - 如果条件满足,则使用
@Bean
方法创建并注册相应的组件到 Spring 容器中。
- 读取绑定的
- 用户覆盖: 如果用户在自己的配置中定义了相同类型的 Bean(且没有条件冲突),根据
@ConditionalOnMissingBean
的逻辑,自动配置提供的默认 Bean 将不会被创建,用户定义的 Bean 生效。
简单来说:
Spring Boot 在启动时会扫描所有 jar 包中的 META-INF/spring.factories
文件,找到声明的自动配置类列表。然后,它根据当前应用的 classpath 内容(有哪些 jar 包)、容器中已有的 Bean、以及配置属性 (application.properties/yml
),智能地选择并加载那些条件满足的自动配置类。这些自动配置类负责创建默认的、开箱即用的组件 Bean。用户可以通过提供自己的 Bean 定义或修改配置属性来覆盖这些默认行为。
理解自动配置原理对于调试 Spring Boot 应用、理解其行为、以及进行高级定制(如创建自己的 Starter)至关重要。你可以通过添加 --debug
参数启动应用,查看 ConditionEvaluationReport
日志,了解哪些自动配置类生效/未生效及其原因。