一、先铺垫:为什么要问 "自动装配原理"?
1.你是否知道 SpringBoot "开箱即用" 的核心原因?(区别于传统 Spring 的繁琐配置)
2.你是否能理解 "注解驱动 + 约定大于配置" 的设计思想?
3.你在使用 SpringBoot 时,是否有思考过 "为什么不用手动配置数据源 / WEB 环境"?
二、通俗解释:SpringBoot 自动装配是什么?
传统 Spring 开发中,你需要手动写大量 XML 配置(比如配置扫描包、数据源、视图解析器、事务管理器),甚至要手动导入第三方框架的配置类;SpringBoot 的自动装配,就是根据你项目中引入的依赖(jar 包),自动识别并配置对应的功能组件,无需手动编写配置,实现 "引入依赖即能用"。比如:你引入了spring-boot-starter-web依赖,SpringBoot 就会自动配置 Tomcat、SpringMVC 的 DispatcherServlet、视图解析器等 WEB 相关组件;你引入了spring-boot-starter-jdbc,它就会自动配置数据源和 JdbcTemplate。
三、核心原理拆解
步骤 1:核心入口注解 ------@SpringBootApplication
SpringBoot 的启动类上都会标注@SpringBootApplication,它不是一个单独注解,而是组合注解,其中负责自动装配的核心是@EnableAutoConfiguration(另外两个注解是辅助作用):
// @SpringBootApplication的底层结构(简化版)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
// 1. 标记为Spring的配置类(等同于@Configuration)
@SpringBootConfiguration
// 2. 开启自动装配(核心!)
@EnableAutoConfiguration
// 3. 扫描当前包及子包下的@Component注解类(Service/Controller等)
@ComponentScan(excludeFilters = ...)
public @interface SpringBootApplication {}
考察点:你是否能说出@SpringBootApplication包含@EnableAutoConfiguration,且知道后者是自动装配的开关。
步骤 2:自动装配的核心 ------@EnableAutoConfiguration
@EnableAutoConfiguration的作用是 "开启自动配置",它的底层依赖@Import(AutoConfigurationImportSelector.class),核心逻辑是:AutoConfigurationImportSelector类会加载所有符合条件的 "自动配置类",并将这些配置类注入 Spring 容器。
SpringBoot读取的是「META-INF/spring.factories」文件,通过键值对org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx.xxx.AutoConfiguration指定自动配置类。
**考察点:**你是否知道自动配置类的加载来源(某个固定目录的文件),是否能说出 1-2 个自动配置类(比如数据源、WEB 相关)。
步骤 3:自动配置类的 "按需生效"------@Conditional 系列注解
加载的自动配置类有上百个,但不是所有都会生效(比如你没引入 Redis 依赖,RedisAutoConfiguration就不会生效),核心是靠@Conditional系列注解做 "条件判断",只有满足条件,该自动配置类才会被 Spring 容器加载。
常用的条件注解:
| 注解 | 作用(通俗理解) |
|---|---|
| @ConditionalOnClass | 项目类路径下存在某个类(比如引入了对应 jar 包),才生效 |
| @ConditionalOnMissingBean | 容器中不存在某个 Bean 时,才自动配置(支持手动覆盖) |
| @ConditionalOnProperty | 配置文件中存在某个属性(比如 spring.redis.host),才生效 |
| @ConditionalOnWebApplication | 当前是 WEB 应用时,才生效 |
举个例子(DataSourceAutoConfiguration简化版):
// 只有类路径下存在DataSource.class(引入了jdbc依赖),才会生效
@ConditionalOnClass(DataSource.class)
// 只有配置文件中存在spring.datasource相关配置(或使用默认配置),才会生效
@ConditionalOnProperty(prefix = "spring.datasource")
@Configuration
public class DataSourceAutoConfiguration {
// 自动配置数据源Bean
@Bean
// 如果用户自己配置了数据源Bean,这个自动配置的Bean就不会生效
@ConditionalOnMissingBean(DataSource.class)
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
**考察点:**你是否理解 "自动配置不是无条件的",是否知道 "手动配置的 Bean 会覆盖自动配置"(这是实际开发中常用的技巧)。
步骤 4:配置绑定 ------@ConfigurationProperties
自动配置类需要读取配置文件(application.yml/application.properties)中的属性(比如spring.datasource.url、server.port),这是通过@ConfigurationProperties注解实现的 "配置绑定"。
比如DataSourceProperties类(负责绑定数据源配置):
// 绑定配置文件中以"spring.datasource"为前缀的属性
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {
private String url;
private String username;
private String password;
private String driverClassName;
// getter/setter
}
当你在 application.yml 中配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
DataSourceProperties会自动读取这些属性,然后被DataSourceAutoConfiguration注入,生成对应的数据源 Bean。
**考察点:**你是否用过@ConfigurationProperties(或@Value)读取配置文件,是否知道配置前缀的含义。
总结:
一句话概述:
SpringBoot 启动时,通过@SpringBootApplication中的@EnableAutoConfiguration,触发AutoConfigurationImportSelector加载配置文件中的自动配置类;这些自动配置类通过@Conditional系列注解按需生效;生效的配置类通过@ConfigurationProperties绑定配置文件属性,最终自动将功能 Bean 注入 Spring 容器,实现 "开箱即用"。
加分项:
-
结合实际项目:"我在项目中引入了spring-boot-starter-redis,不用手动配置 RedisTemplate,就是自动装配的作用;后来我需要自定义 Redis 序列化方式,就自己创建了 RedisTemplate Bean,覆盖了自动配置的 Bean";
-
理解设计思想:"自动装配的核心是'约定大于配置',减少了手动配置的工作量,同时保留了手动覆盖的灵活性";
-
知道扩展方式:"如果想排除某个自动配置类,可以用@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)"。