[面试题] 什么是 BeanDefinition?它和 Bean 有什么区别?
📖 版块 A:知识讲解版 (温故知新)
-
BeanDefinition:
- 是 Spring 对 Bean 的抽象定义,可以理解成 Bean 的“元数据”或“施工图纸”。
- 里面通常包含类名、作用域、是否懒加载、构造参数、属性依赖、初始化方法、销毁方法等信息。
- 它本身还不是那个真正已经创建出来的对象。
-
Bean:
- 是 Spring 根据 BeanDefinition 真正实例化出来的对象。
- 它已经经历了实例化、依赖注入、初始化等生命周期阶段,可以直接被业务代码使用。
-
两者关系:
- Spring 先有 BeanDefinition,再有 Bean。
- BeanDefinition 负责描述“怎么造”,Bean 负责作为“造出来的成品”被使用。
-
为什么要分两层:
- 方便 Spring 在对象真正创建之前,先统一收集、管理和修改所有定义。
- 这也给 BeanFactoryPostProcessor、ConfigurationClassPostProcessor 这类扩展点留下了空间。
🎤 版块 B:面试实战版 (高手逐字稿)
Q:什么是 BeanDefinition?它和 Bean 有什么区别?
💬 高手逐字稿:
在 Spring 里,BeanDefinition 和 Bean 不是同一个层面的概念。
BeanDefinition 可以理解成 Spring 对一个 Bean 的“元数据描述”。它里面记录的不是对象本身,而是“这个对象未来应该怎么被创建、怎么被管理”。比如类名是什么、作用域是单例还是多例、是否懒加载、需要注入哪些属性、初始化方法和销毁方法是什么,这些信息都属于 BeanDefinition 的范畴。
而 Bean 才是 Spring 真正创建出来的那个对象。也就是说,Spring 会先把配置、注解、@Bean 方法这些信息解析成 BeanDefinition,然后在真正需要的时候,再根据这个定义去实例化对象、注入依赖、执行初始化逻辑,最后得到可用的 Bean。
为什么 Spring 不直接一步到位创建对象,而是非要先搞一层 BeanDefinition?我觉得核心是两个原因。
第一,统一管理定义信息。这样 Spring 可以在对象真正创建之前,先把全局的 Bean 都登记清楚,形成一个完整的“定义仓库”。
第二,方便扩展和改造。很多 Spring 的源码扩展点,其实都是作用在 BeanDefinition 阶段。比如 BeanFactoryPostProcessor 可以在对象创建前去修改 BeanDefinition,ConfigurationClassPostProcessor 也会不断向容器里追加新的 BeanDefinition。如果没有这层定义抽象,Spring 的扩展性会差很多。
所以一句话总结:BeanDefinition 解决的是“描述对象”,Bean 解决的是“使用对象”,Spring 先管理定义,再延迟落成实例。