SpringBoot的自动配置原理
目录
- 一、自动配置的入口:@SpringBootApplication
- 1. @SpringBootApplication 源码解析
- 2. 关键结论
- 二、自动配置的核心:@EnableAutoConfiguration
- 1. @Import:导入自动配置选择器
- 2. AutoConfigurationImportSelector:筛选自动配置类
- 步骤 1:加载自动配置类候选列表
- 步骤 2:根据条件注解过滤无效配置类
- 3. 配置属性绑定:@EnableConfigurationProperties
- 原理:绑定配置文件与属性类
一、自动配置的入口:@SpringBootApplication
SpringBoot 自动配置的一切,都从启动类上的@SpringBootApplication
开始。它并非全新注解,而是三个核心 Spring 注解的 “组合注解”,其中@EnableAutoConfiguration
是触发自动配置的关键。
1. @SpringBootApplication 源码解析
先看它的核心结构(已标注关键注释):
@Target(ElementType.TYPE) // 注解作用于类/接口
@Retention(RetentionPolicy.RUNTIME) // 运行时生效
@Documented // 生成文档时包含该注解
@Inherited // 子类可继承父类的该注解
// 1. 核心:开启自动配置(自动配置的总开关)
@EnableAutoConfiguration
// 2. 扫描当前包及子包下的@Component注解(@Service/@Controller/@Repository等)
@ComponentScan(excludeFilters = { // 过滤自动配置类(避免重复扫描)@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }
)
// 3. 标记当前类为配置类(支持用@Bean定义Bean,替代XML配置)
@Configuration
public @interface SpringBootApplication {// 手动排除指定自动配置类(避免与自定义配置冲突)Class<?>[] exclude() default {};// 通过类名排除自动配置类(用于配置文件中指定,更灵活)String[] excludeName() default {};
}
2. 关键结论
@SpringBootApplication
的核心是@EnableAutoConfiguration
:它告诉 SpringBoot“去加载所有符合条件的自动配置类,并把类中的 Bean 装配到 IoC 容器”;- 另外两个注解是 “辅助角色”:
@ComponentScan
负责扫描自定义 Bean,@Configuration
允许手动定义配置,三者配合实现 “自动 + 手动” 的配置融合。
二、自动配置的核心:@EnableAutoConfiguration
@EnableAutoConfiguration
是自动配置的 “大脑”,它通过两个关键组件实现功能:@Import
注解和AutoConfigurationImportSelector
类。
1. @Import:导入自动配置选择器
先看@EnableAutoConfiguration
的源码核心:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// 关键:导入自动配置类的“筛选器”——AutoConfigurationImportSelector
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {// 可通过配置关闭自动配置(默认开启)String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";// 同@SpringBootApplication的exclude,用于排除自动配置类Class<?>[] exclude() default {};String[] excludeName() default {};
}
@Import
是 Spring 原生注解,作用是将指定类实例化并注入 IoC 容器。这里导入的AutoConfigurationImportSelector
,就是负责 “筛选哪些自动配置类需要生效” 的核心类。
2. AutoConfigurationImportSelector:筛选自动配置类
AutoConfigurationImportSelector
的核心逻辑在selectImports()
方法中,它会返回 “需要生效的自动配置类全限定名数组”。整个筛选流程可拆解为 3 步:
步骤 1:加载自动配置类候选列表
SpringBoot 在启动时,会读取一个固定路径的文件:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
(SpringBoot 2.7 + 版本)。
注意:2.7 之前的版本是
META-INF/spring.factories
,格式为org.springframework.boot.autoconfigure.EnableAutoConfiguration=配置类全限定名
,2.7 + 简化为直接写配置类路径。
这个文件中存储了 SpringBoot 内置的所有 “自动配置类”,比如:
# Web相关配置
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
# 数据库相关配置
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
# JPA相关配置
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration
# 日志相关配置
org.springframework.boot.autoconfigure.logging.LoggingAutoConfiguration
...
这些类对应了 Web、数据库、日志等常见场景,是自动配置的 “候选池”。
步骤 2:根据条件注解过滤无效配置类
候选列表中的自动配置类并非全部生效,每个类上都标注了 **@Conditional
系列条件注解 **,只有满足条件的类才会被加载到 IoC 容器。
以数据库连接池配置DataSourceAutoConfiguration
为例:
@Configuration(proxyBeanMethods = false)
// 条件1:类路径下存在DataSource和EmbeddedDatabaseType(即引入了数据库依赖)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
// 条件2:容器中不存在R2DBC的ConnectionFactory(避免与R2DBC冲突)
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
// 绑定配置文件属性(下文会讲)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {// 配置DataSource Bean的逻辑(初始化连接池)@Bean@ConditionalOnMissingBeanpublic DataSource dataSource(DataSourceProperties properties) {return DataSourceBuilder.create().url(properties.getUrl()).username(properties.getUsername()).password(properties.getPassword()).build();}
}
最后,SpringBoot 会根据两种方式排除不需要的自动配置类:
- 代码级:
@SpringBootApplication(exclude = 配置类.class)
; - 配置级:
application.yml
中配置spring.autoconfigure.exclude=配置类全限定名
。
例如,若手动配置了 Druid 数据源,可排除默认的DataSourceAutoConfiguration
:
// 代码级排除
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}
或在配置文件中排除:
yaml
# 配置级排除
spring:autoconfigure:exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
3. 配置属性绑定:@EnableConfigurationProperties
自动配置类不仅会创建 Bean,还会读取application.yml
中的配置动态调整 Bean 参数(比如数据库 URL、端口号),这靠@EnableConfigurationProperties
实现。
原理:绑定配置文件与属性类
以DataSourceAutoConfiguration
为例:
- 类上标注
@EnableConfigurationProperties(DataSourceProperties.class)
,表示 “将DataSourceProperties
与配置文件绑定”; DataSourceProperties
类用@ConfigurationProperties(prefix = "spring.datasource")
指定属性前缀,自动读取spring.datasource.xxx
格式的配置;- 自动配置类创建
DataSource
时,注入DataSourceProperties
,用其属性初始化连接池。
DataSourceProperties
核心源码:
// 绑定配置文件中“spring.datasource”前缀的属性
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {// 默认值:若用户未配置,用默认驱动private String driverClassName;private String url;private String username;private String password;// 数据源类型(如com.alibaba.druid.pool.DruidDataSource)private Class<? extends DataSource> type;// getter/setter方法// ...
}
用户只需在application.yml
中配置:
spring:datasource:url: jdbc:mysql://localhost:3306/mydbusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver
SpringBoot 会自动将这些配置注入DataSourceProperties
,再用它初始化DataSource
Bean。