@EnableAutoConfiguration是Spring Boot自动装配总开关,通过AutoConfigurationImportSelector读取META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports加载条件化配置类,配合@ConditionalOnClass和@ConditionalOnMissingBean实现按需装配。

Spring Boot自动装配靠的是@EnableAutoConfiguration
这个注解是自动装配的总开关,它本身不干具体事,而是通过导入AutoConfigurationImportSelector来触发配置类的条件化加载。你写@SpringBootApplication,其实就等价于同时写了@EnableAutoConfiguration、@ComponentScan和@SpringBootConfiguration。
关键点在于:AutoConfigurationImportSelector会读取所有META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Spring Boot 2.7+)或旧版的META-INF/spring.factories文件,拿到候选的自动配置类全限定名列表。
- Spring Boot 2.7+ 强制使用
AutoConfiguration.imports,不再支持spring.factories中的org.springframework.boot.autoconfigure.EnableAutoConfiguration键 - 每个自动配置类都必须用
@Configuration标记,且通常搭配@ConditionalOnClass、@ConditionalOnMissingBean等条件注解 - 条件不满足时,该配置类直接被跳过,不会报错也不会注册任何Bean
@ConditionalOnClass和@ConditionalOnMissingBean怎么协同工作
这是自动装配“按需生效”的核心机制:前者控制“能不能装”,后者控制“要不要装”。比如DataSourceAutoConfiguration里有:
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "javax.sql.DataSource", search = SearchStrategy.CURRENT)
意思是:只有当前类路径下存在DataSource类(比如引入了spring-jdbc),且用户没自己定义DataSource类型的Bean时,才去创建默认的HikariDataSource。
立即学习“Java免费学习笔记(深入)”;
-
@ConditionalOnClass检查的是类是否在ClassLoader中可加载,不是看jar包是否存在;如果类存在但依赖缺失(如缺少mysql-connector-java),运行时报NoClassDefFoundError,不是条件判断失败 -
@ConditionalOnMissingBean的search参数很重要:默认CURRENT只查当前容器,设为ALL会递归查父容器,可能意外跳过你的自定义Bean - 多个条件注解是“与”关系,任一不满足,整个配置类就被忽略
自定义Starter里怎么写自动配置类
写一个能被自动加载的Starter,必须保证三件事:配置类在AutoConfiguration.imports里声明、类上有@Configuration、内部Bean注册逻辑带合理条件。
例如你开发my-spring-boot-starter,在模块的src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports里写:
com.example.myautoconfigure.MyServiceAutoConfiguration
然后定义配置类:
@Configuration
@ConditionalOnClass(MyService.class)
@ConditionalOnProperty(prefix = "my.service", name = "enabled", havingValue = "true", matchIfMissing = true)
public class MyServiceAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService() {
return new MyServiceImpl();
}
}
- 别漏掉
@Configuration——没有它,即使类被加载,里面的@Bean方法也不会执行 - 推荐用
@ConditionalOnProperty给用户留开关,默认开启(matchIfMissing = true),比硬编码更友好 - 不要在自动配置类里做耗时操作(如网络请求、文件扫描),否则拖慢启动速度;初始化逻辑应延迟到Bean首次使用时(用
@Lazy或设计成懒加载)
为什么@EnableAutoConfiguration(exclude = ...)有时不生效
排除失效最常见的原因是:你想排除的类根本没被纳入候选列表,或者被其他自动配置类提前注册了同类型Bean。
- 确认排除的类名完全匹配,包括包路径;错误示例:
exclude = DataSourceAutoConfiguration.class写成exclude = "DataSourceAutoConfiguration"(字符串方式必须带全限定名) - 如果用
@SpringBootApplication(exclude = ...),它只影响当前模块的@EnableAutoConfiguration导入,不影响第三方Starter自己触发的导入 - 更稳妥的方式是在
application.properties里关掉:比如spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - 排除后仍看到相关Bean?用
ApplicationContext.getBeanDefinitionNames()或启动加--debug参数,看实际注册了哪些Bean及其来源
@ConditionalOnClass误判,以及排除机制和多层Starter之间的优先级冲突。










