[面试题] 聊聊Spring的BeanFactory 和 FactoryBean?
📖 版块 A:知识讲解版 (温故知新)
-
BeanFactory:
- 本质:是 Spring 容器的顶层核心接口,是整个 IoC 容器的底层基础设施。
- 职责:负责管理 Bean 的生命周期,包括实例化、定位、配置对象及建立对象间的依赖关系。
- 特点:采用了延迟加载策略(Lazy-load),只有在第一次调用
getBean()时才会实例化 Bean。
-
FactoryBean:
-
本质:是一个特殊的 Bean,由 Spring 容器管理,但它本身是一个工厂。
-
职责:用于封装复杂的初始化逻辑。如果一个 Bean 的创建过程非常复杂(例如需要大量配置、动态代理或集成第三方库),不适合简单的 XML/注解定义,就可以通过实现
FactoryBean接口来自定义实例化逻辑。 -
核心方法:
getObject():返回由 FactoryBean 创建的实例。getObjectType():返回创建对象的类型。isSingleton():标识创建的对象是否为单例。
-
-
区别总结:
BeanFactory是“管理者的容器”,它产出的是普通的 Bean。FactoryBean是“生产者的 Bean”,它本身就在容器中,但它通过getObject()产出另一个特定的 Bean。
🎤 版块 B:面试实战版 (高手逐字稿)
Q:聊聊 Spring 的 BeanFactory 和 FactoryBean?
💬 高手逐字稿:
这两个概念在 Spring 中虽然名字很像,但定位完全不同。
首先,BeanFactory 是 Spring 框架最核心的顶层接口。我们可以把它理解为 Spring 容器本身。它定义了容器最基本的形式,负责管理 Bean 的生命周期,比如 getBean、containsBean 等基础功能都是它定义的。我们常用的 ApplicationContext 其实就是它的一个子接口,并在它的基础上增加了 AOP、国际化和事件传播等更高级的功能。
其次,FactoryBean 是一个特殊的 Bean。它本质上是一个能够产生对象的工厂 Bean。在 Spring 中,如果我们想创建一个非常复杂的对象,比如这个对象需要经过繁琐的配置,或者是一个动态代理对象(像 MyBatis 的 Mapper 接口、Dubbo 的远程调用代理),如果用传统的 XML 或注解配置会非常麻烦。这时候我们就可以实现 FactoryBean 接口,把复杂的初始化逻辑封装在它的 getObject() 方法里。
这里有一个容易被忽略的细节:当我们调用 getBean("userFactoryBean") 时,Spring 返回的并不是 UserFactoryBean 这个类本身,而是它内部 getObject() 方法返回的那个实例。如果你确实想要获取这个工厂 Bean 自身的实例,就需要在 beanName 前面加上一个前缀 &,也就是调用 getBean("&userFactoryBean")。
在我的实际开发经验中,这种模式在框架整合时非常普遍。比如 MyBatis 集成 Spring 时,核心类 SqlSessionFactoryBean 就是一个 FactoryBean。Spring 并不是直接通过反射创建一个 SqlSessionFactory,而是通过这个 FactoryBean 内部复杂的逻辑去解析配置文件、构建环境,最后才交付给开发者使用。
所以总结一下:BeanFactory 是 Spring 容器的基础设施,负责“怎么管”;而 FactoryBean 是对 Spring 创建 Bean 能力的扩展,负责“怎么造”。