一、自动配置的核心入口:@SpringBootApplication 与 @EnableAutoConfiguration
面试官: SpringBoot自动配置的原理是什么?
嗯,好的,它是这样的。
其实SpringBoot自动配置的核心,是引导类上加的注解
@SpringBootApplication
底层封装的一个注解,叫@EnableAutoConfiguration
,这个注解才是实现自动化配置的核心注解。该注解通过
@Import
注解导入对应的配置选择器,导入了一个ImportSelector接口的实现类。 而在这个类的内部呢,读取了该项目和该项目引用的Jar包中的classpath路径下META-INF/spring.factories
文件中的所配置的类的全类名。在这些配置类中所定义的Bean,会根据条件注解@Condition系列注解所指定的条件来决定是否需要将其导入到Spring容器中。
一般条件判断会有像
@ConditionalOnClass
这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个配置类的所有的Bean放入spring容器中使用。但是这里要说明一点哈,就是刚才提到的系统配置类声明的配置文件
META-INF/spring.factories
, 在springboot3.0版本之后,就已经废除了,不会在这个文件中配置自动配置类了,替换成了一份新的配置文件,配置文件名比较长,记不住,后缀名为:XXxxxSpringAutoConfiguration.imports
。
接下来我们来详细了解它
刚创建 Spring Boot 项目时,启动类上的@SpringBootApplication注解是自动配置的起点。它其实是个 "组合套餐",包含了三个关键注解:
- @SpringBootConfiguration:标记启动类为配置类,等价于@Configuration,允许在类中定义@Bean方法,这些方法返回的对象会被 Spring 容器管理,成为应用中的 Bean。
- @ComponentScan:扫描启动类所在包及其子包,把@Controller、@Service、@Repository、@Component等组件纳入 Spring 容器。默认情况下,它会将扫描到的类注册为 Spring Bean,让这些组件能够被 Spring 管理和使用 。
- @EnableAutoConfiguration:核心中的核心,作用是 "开启自动配置",告诉 Spring Boot:"嘿,该干活了,根据依赖自动配置配置类吧!" 点开@EnableAutoConfiguration源码会发现,它通过@Import(AutoConfigurationImportSelector.class)引入了一个关键处理器AutoConfigurationImportSelector,这个处理器的任务是从META-INF/spring.factories文件中读取所有候选的自动配置类,再按需导入到 Spring 容器里。
二、SPI 机制:自动配置类的 "注册表"
Spring Boot 的自动配置离不开 Java 的 SPI(Service Provider Interface)机制,简单来说,SPI 就像一个 "服务注册表",允许第三方通过特定文件注册自己的实现。在 Spring Boot 中,每个自动配置模块(比如数据库、Web 模块)的 JAR 包里,都有一个META-INF/spring.factories文件。文件里以键值对形式列出了所有可用的自动配置类,例如:当应用启动时,Spring 会扫描所有依赖 JAR 包中的META-INF/spring.factories,把org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的配置类全加载到内存,形成候选列表。这一步就像把所有可能用到的配置类先 "摆上桌",等着后续筛选。
三、条件注解:按需激活配置类的 "开关"
把所有配置类摆上桌后,不能一股脑全用上,得根据项目实际情况筛选。比如项目没连数据库,就没必要加载数据源配置类。这时,Spring Boot 的条件注解就派上用场了,它们是配置类的 "激活开关"。
常见条件注解
- @ConditionalOnClass:类路径下存在指定类时,配置类才生效。比如DataSourceAutoConfiguration上有这个注解,当项目引入数据库依赖(存在DataSource类)时,这个配置类才会被激活。
- @ConditionalOnMissingBean:容器中不存在指定类型的 Bean 时,配置类才生效。比如用户自己定义了一个DataSource Bean,自动配置的数据源就不会重复创建,避免冲突。
- @ConditionalOnProperty:根据配置文件中的属性判断。比如@ConditionalOnProperty(name = "spring.cache.enabled", havingValue = "true"),只有当spring.cache.enabled=true时,缓存相关配置类才生效。
示例:数据源自动配置类
以DataSourceAutoConfiguration数据源自动配置类为例,它上面可能同时存在@ConditionalOnClass(DataSource.class)和@ConditionalOnMissingBean(DataSource.class)等注解 。这一串注解保证了:只有项目需要数据库(有DataSource类),且用户没自己配置数据源时,自动配置才会生效,既智能又灵活。
四、自动配置的完整流程:从启动到 Bean 注册
Spring Boot 应用启动时,自动配置会按以下步骤 "悄悄工作":
1. 启动应用,触发自动配置
调用SpringApplication.run()后,Spring Boot 先解析启动类上的@SpringBootApplication,尤其是其中的@EnableAutoConfiguration,激活自动配置流程。
2. 收集候选配置类
扫描所有依赖 JAR 包的META-INF/spring.factories,把org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的类全收集起来,比如DataSourceAutoConfiguration、WebMvcAutoConfiguration等,形成一个 "候选清单"。
3. 按条件过滤配置类
对每个候选配置类,逐一检查条件注解。比如检查项目是否有 Web 依赖(存在Servlet类),决定是否保留WebMvcAutoConfiguration;检查用户是否自定义了 Bean,决定是否跳过某个自动配置。这一步会过滤掉不符合当前项目场景的配置类,只留下 "有用的"。
4. 注册 Bean 到容器
对通过条件检查的配置类,解析其中的@Bean方法,创建 Bean 定义并注册到 Spring 容器。比如WebMvcAutoConfiguration会注册DispatcherServlet、HandlerMapping等 Web 开发必需的组件,让 Spring MVC 能正常工作。整个流程就像 "按需组装零件",项目需要什么功能,就激活对应的配置类,注册对应的 Bean,不需要的绝不加载,既高效又节省资源。
五、自定义自动配置:扩展 Spring Boot 的 "魔法"
掌握了自动配置原理后,我们可以自己定制配置类,让 Spring Boot 按我们的规则工作。
步骤 1:创建自定义配置类
新建一个配置类,比如MyAutoConfiguration,用@Configuration标记它是个配置类,添加条件注解控制生效条件,在类里用@Bean方法定义需要的 Bean 。例如:
kotlin
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConditionalOnClass;
import org.springframework.context.annotation.ConditionalOnMissingBean;
@Configuration
@ConditionalOnClass(MyService.class)
@ConditionalOnMissingBean(MyService.class)
public class MyAutoConfiguration {
@Bean
public MyService myService() {
return new MyService();
}
}
上述代码中,@ConditionalOnClass(MyService.class)表示只有当MyService类在类路径下存在时,这个配置类才生效;@ConditionalOnMissingBean(MyService.class)表示当容器中不存在MyService类型的 Bean 时,才会创建这个 Bean。
步骤 2:注册到 spring.factories
在项目的src/main/resources/META-INF目录下创建spring.factories文件,加入:
ini
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfig.MyAutoConfiguration
这样,当其他项目引入你的依赖时,Spring Boot 会自动发现并加载这个自定义配置类,实现 "开箱即用" 的自定义功能。
注意:用户配置优先
如果用户自己定义了MyService Bean,Spring Boot 会让自动配置失效,保证用户自定义逻辑优先,这也是 Spring Boot "约定优于配置" 的体现。
六、总结:自动配置如何让开发更简单?
Spring Boot 的自动配置通过收集候选配置类,用条件注解按需激活,按规则注册 Bean,实现了 "根据依赖和配置自动装配" 的魔法。开发者不用手动编写大量配置类,只要引入依赖,Spring Boot 就会 "猜" 出你需要的功能,自动搭好架子。理解这套原理后,不仅能更熟练地使用 Spring Boot,还能自定义配置类扩展功能,甚至排查自动配置不生效的问题(比如检查条件注解是否满足、Bean 是否正确注册)。下次遇到自动配置相关的问题,就可以顺着 "SPI 加载→条件过滤→Bean 注册" 的流程一步步分析,再也不怕 "魔法失效" 啦!