Spring 配置的最终产物都是 BeanDefinition。@Component、@Bean、@Import 和自动配置只是不同的定义来源,理解这一点就能统一排查“为什么这个 Bean 出现或缺失”。
Table of contents
Open Table of contents
从配置类开始实验
LabConfiguration下载声明一个 Clock:
@Configuration(proxyBeanMethods = false)
class LabConfiguration {
@Bean Clock clock() { return Clock.systemDefaultZone(); }
}
proxyBeanMethods=false 表示不需要用 CGLIB 拦截配置类内部方法调用,适合各 @Bean 方法彼此不直接调用的配置,启动成本和语义都更清楚。
配置解析主线
ConfigurationClassPostProcessor 是 BeanFactoryPostProcessor。它在普通单例创建前解析:
- 配置类候选;
@ComponentScan找到的组件;@Import导入类、Selector 和 Registrar;@Bean工厂方法;@Conditional是否满足;- 将结果注册为 BeanDefinition。
组件扫描以启动类所在包为默认根。把启动类放得太深会漏扫,把根放得太高又可能纳入测试或其他应用配置。大型系统更适合显式模块配置和 @Import。
条件装配必须可解释
条件可以检查类路径、Bean、属性或 Web 应用类型。自动配置通常使用“类存在、用户尚未提供同类 Bean”作为后备方案。
条件只在注册阶段决定定义是否出现,不应拿它实现运行时每请求业务分支。排查时查看 Condition Evaluation Report,确认哪个条件匹配或不匹配,而不是盲目增加扫描路径。
配置边界就是模块边界
一个模块对外提供少量配置入口,内部组件保持包私有;调用方通过 @Import 或启动器显式启用。这样测试可以只加载所需模块,也能避免同名 Bean 和意外扫描。
下一步
阅读Spring 扩展点实战,按“修改配方、注册配方、加工对象、接收事件”选择正确接口。