← 返回题目列表

Spring FactoryBean 和工厂方法模式有什么区别?

高频 中等 第 12 / 25 题 更新于 2026/08/01
工厂方法模式SpringFactoryBeanBeanFactory

简化版

FactoryBean 是 Spring 提供的扩展接口,用来让某个 Bean 负责生产另一个 Bean;工厂方法模式是通用设计模式,用抽象工厂方法延迟具体产品创建。FactoryBean 可以体现工厂思想,但它是容器机制的一部分,不等同于 GoF 工厂方法模式。

详细版

Spring 中容易混淆三个概念:BeanFactoryFactoryBean 和工厂方法模式。BeanFactory 是 Spring 容器的基础接口,负责管理 Bean;FactoryBean<T> 是一种特殊 Bean,容器调用它的 getObject() 获得真正暴露给业务的对象;工厂方法模式则是一种面向对象创建型模式。

FactoryBean 常用于复杂对象创建,比如代理对象、连接客户端、Mapper、框架适配对象。它的重点不是让子类覆盖创建方法,而是把复杂创建逻辑接入 Spring 生命周期、依赖注入和作用域管理。

面试回答可以抓住:

概念角色
BeanFactory容器本身
FactoryBean生产 Bean 的特殊 Bean
工厂方法模式解耦产品创建的设计模式

所以 FactoryBean 可以是工厂模式在 Spring 中的工程化落地,但不能简单说它就是工厂方法模式。

完整版教学

一、先区分 BeanFactory 和 FactoryBean

BeanFactory 是 Spring 容器接口,负责根据 Bean 定义创建、装配、缓存和返回 Bean。FactoryBean 则是用户实现的一个特殊 Bean,它本身被容器管理,但它生产的对象才是普通 getBean() 返回的主要对象。

BeanFactory:Spring 容器
FactoryBean:容器里的一个特殊工厂 Bean
getObject():生产真正业务对象

名字相近是这题的主要陷阱。面试里如果把 BeanFactoryFactoryBean 说反,基本说明对 Spring 容器机制不熟。

二、FactoryBean 的基本工作方式

一个 FactoryBean<T> 通常实现三个方法:getObject() 返回产品对象,getObjectType() 返回产品类型,isSingleton() 告诉容器产品是否按单例语义缓存。

public class ClientFactoryBean implements FactoryBean<Client> {
    @Override
    public Client getObject() {
        return new Client("https://api.example.com");
    }

    @Override
    public Class<?> getObjectType() {
        return Client.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

如果注册 Bean 名为 client,通常 getBean("client") 返回的是 Client,而不是 ClientFactoryBean 本身。要拿工厂本身,需要使用特殊前缀 &client

三、它和工厂方法模式相似在哪里

相似点在于都把对象创建封装起来,调用方不直接 new 复杂对象。业务代码只依赖最终产品,比如 Client 接口,而不用知道它是否由代理、反射、配置文件或网络元数据创建。

例如 MyBatis 的 Mapper 代理、AOP 代理、某些客户端 SDK 都可能需要复杂创建过程。用 FactoryBean 后,复杂过程被封装在 getObject() 中,容器仍能完成依赖注入和生命周期管理。

业务类 -> 注入 Client
Spring -> 调用 FactoryBean.getObject()
FactoryBean -> 创建代理/客户端/适配对象

这种思想符合工厂封装创建的精神,但实现方式是 Spring 容器协议,不是标准 GoF 角色结构。

四、它和 GoF 工厂方法模式不同在哪里

GoF 工厂方法模式强调“抽象 Creator 声明工厂方法,具体 Creator 决定创建哪种 Product”。FactoryBean 更强调“让容器通过统一协议取得某个复杂 Bean”。它不要求有一组具体工厂子类,也不要求客户端持有工厂抽象。

维度FactoryBean工厂方法模式
所属领域Spring 容器扩展点通用设计模式
创建入口getObject()抽象工厂方法
生命周期由 Spring 管理由代码设计决定
调用方通常直接注入产品可能依赖工厂抽象
典型目的接入复杂 Bean 创建多态扩展产品创建

所以更准确的表述是:FactoryBean 是 Spring 用来定制 Bean 创建的机制,内部可以运用工厂方法思想。

五、& 前缀为什么是高频追问

因为 FactoryBean 本身也是一个 Bean,但默认名字返回的是它生产的对象。Spring 用 & 前缀区分“我要产品”还是“我要工厂本身”。

getBean("client")  -> ClientFactoryBean.getObject() 的结果
getBean("&client") -> ClientFactoryBean 实例本身

假设 client 的产品对象是 1 个代理客户端,工厂对象也是 1 个 Bean。如果你调试时发现类型对不上,首先要检查是否混淆了这两个层级。这也是很多 Spring 面试会问 FactoryBean 的原因。

记忆钩子:BeanFactory 是容器,FactoryBean 是容器里的工厂,&name 拿工厂本身,name 拿产品。

六、FactoryBean 的单例语义要谨慎理解

isSingleton() 描述的是 FactoryBean 生产的对象是否按单例语义处理,不是说工厂类本身是否只有一个。工厂 Bean 本身也受 Spring Bean scope 影响。

一个数字例子:如果 isSingleton() 返回 true,连续 100 次 getBean("client") 应返回同一个产品引用;如果返回 false,容器可能每次调用 getObject() 产生新对象。具体还要结合 Spring 版本和缓存策略理解,但面试层面要把工厂对象和产品对象两层分开。

如果产品对象持有连接池、线程池等资源,单例/多例语义还会影响资源释放。复杂资源更要配合销毁回调,而不是只实现 getObject()

七、什么时候使用 FactoryBean

适合使用 FactoryBean 的场景通常有三个特点:

  1. 产品对象创建过程复杂,普通构造器或 @Bean 方法不够表达;
  2. 产品可能是动态代理或框架对象,不是简单 POJO;
  3. 希望创建过程接入 Spring 的依赖注入、类型推断和生命周期。

如果只是创建一个普通服务类,直接 @Component@Bean 更清楚。过度使用 FactoryBean 会让 Bean 来源难追踪,也会增加调试成本。

八、常见误区与追问

  • 误区:BeanFactory 和 FactoryBean 是同一个东西。 前者是容器接口,后者是用户可实现的特殊工厂 Bean。
  • 误区:FactoryBean 就等于 GoF 工厂方法模式。 它可以体现工厂思想,但本质是 Spring 扩展机制。
  • 误区:getBean("x") 一定返回工厂对象。 对 FactoryBean 来说默认返回产品对象,&x 才返回工厂本身。
  • 误区:isSingleton() 只影响 FactoryBean 自己。 它主要描述产品对象的单例语义。
  • 追问:FactoryBean 适合创建什么对象? 动态代理、复杂客户端、框架适配对象和无法直接构造的产品。
  • 追问:普通 @Bean 方法是不是工厂方法? 它是 Spring 配置中的工厂方法写法,但不等于完整 GoF 工厂方法模式。
  • 追问:FactoryBean 的坏处是什么? 增加理解和调试成本,过度使用会隐藏产品对象创建路径。

九、加强记忆

这题按三层记:BeanFactory 是容器,FactoryBean 是特殊 Bean,工厂方法模式是通用创建型模式。回答时再补上 getObject()getObjectType()isSingleton()&name 语义,基本就能覆盖高频追问。