加个依赖,Bean 自己出现了
引入 spring-boot-starter-data-redis,一行配置没写,RedisTemplate 直接注入就能用——谁 new 的它?没有魔法,只有一条清晰的机制链,源头就藏在 @SpringBootApplication 里。
三件套:注解拆开看
@SpringBootApplication 是组合注解,三件套各司其职:@SpringBootConfiguration——本质是 @Configuration,声明这是配置类;@ComponentScan——扫描主类所在包及子包,这就是「启动类必须放最外层」的原因;@EnableAutoConfiguration——自动装配的开关,今天的主角。它内部通过 @Import(AutoConfigurationImportSelector.class) 引入了一个「清单加载器」:启动时去读一份候选名单,把名单里的自动配置类批量塞进容器。
清单在哪:一份文件的变化
Boot 2.7 之前,候选名单写在各 jar 的 META-INF/spring.factories 里,键为 EnableAutoConfiguration;2.7 起迁移、3.0 定稿为 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports——一个纯文本文件,每行一个自动配置类的全限定名。所有 starter 的清单合并起来几百个候选,但候选不等于生效——能不能进容器,还要过条件装配这一关。
@Conditional:按需过滤的漏斗
自动配置类上挂满 @Conditional 家族注解:@ConditionalOnClass——classpath 里必须有某个类(引了 redis 依赖才有 RedisOperations 类,配置才生效);@ConditionalOnMissingBean——容器里没有用户自己定义的同类型 Bean 才给默认(用户优先原则,你配了就用你的,没配才给默认);@ConditionalOnProperty——配置开关控制。漏斗层层筛完,几百个候选通常只剩几十个真正生效。
@AutoConfiguration
@ConditionalOnClass(SmsClient.class) // classpath 有 SmsClient 才生效
@ConditionalOnProperty(name = "sms.enabled", havingValue = "true", matchIfMissing = true)
public class SmsServiceAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 用户自己定义了 SmsService 就不给默认的
public SmsService smsService(SmsProperties properties) {
return new SmsService(properties);
}
}排查利器:ConditionEvaluationReport
搞不清某个自动配置为什么没生效?启动加 --debug 参数(或配置 debug=true),控制台会打印完整报告:Positive matches 列出生效的与命中的条件,Negative matches 列出没生效的与没命中的原因——哪个 @ConditionalOnClass 没找到类、哪个 @ConditionalOnProperty 值不对,一目了然。这是排查自动装配的第一工具,比翻源码快得多。
下一篇动手实践:看懂了自动装配的规则,就照着规则自己写一个 Starter,把公司组件封装成标准件。
评论 (0)