Skip to content

Spring 中的 FactoryBean 是什么? ​

  • 标签:后端、Spring

🏛 业务架构师 ​

FactoryBean 是一个"生产 Bean 的 Bean"——它本身注册在容器里,但 getBean 拿到的不是它,而是它的 getObject() 返回的产品。它解决的是**"创建逻辑复杂、无法简单 new 出来"的对象如何纳入容器统一管理**的问题。

经典的业务场景:

  1. 集成第三方 SDK:MyBatis 的 SqlSessionFactoryBean、老版本的各种 Client 封装,创建过程涉及大量初始化步骤,用 FactoryBean 包一层,业务方就能像用普通 Bean 一样注入使用;
  2. 动态代理类装配:Feign 客户端就是典型——接口没有实现类,FactoryBean 在运行期生成代理并交给容器,业务方注入接口即可远程调用;
  3. 同构多实例:按配置动态决定返回哪个实现,把"选型逻辑"收敛到一处。

和 BeanFactory 的区别必须说清(面试高频混淆点):BeanFactory 是容器(管理所有 Bean 的工厂),FactoryBean 是容器里一个特殊的 Bean(负责生产某个特定对象)——一个是"工厂本身",一个是"工厂里的一台专用机床"。

业务取舍上我的原则:只有当创建逻辑确实复杂或需要动态性时才上 FactoryBean,普通场景 @Bean 方法足够。它的调试成本不低(getBean 行为不直观),为简单对象引入它属于典型的过度设计。

🏗 系统架构师 ​

FactoryBean 是「生产 Bean 的 Bean」:容器最终注入的是 getObject() 的返回值,getBean("&xxx") 才拿到工厂本身。它是工厂模式在框架层的 SPI,典型用途是把动态生成的对象接入容器:

  • MyBatis 的 MapperFactoryBean:把 Mapper 接口的动态代理注册成 Bean;
  • OpenFeign 的 FeignClientFactoryBean:为每个 @FeignClient 接口生成远程调用代理;
  • Dubbo、Nacos 的集成也大量使用。

架构视角:当 Bean 不是「new 加注入」能造出来、而需要动态代理或复杂构建(连接、加密、配置解析)时,就走 FactoryBean。它与 @Bean 的分工是:@Bean 解决「第三方类不好加注解」的装配问题,FactoryBean 解决「对象本身是运行时生成的」问题。评审框架集成方案时,我会检查它是否正确暴露 isSingleton 与类型信息——这直接影响注入匹配与启动成本。

💻 全栈开发专家 ​

FactoryBean 是一种特殊的 Bean,用来定制"生产另一个 Bean"的过程。它自己注册进容器,但 getBean("xxx") 拿到的是它 getObject() 返回的产品;想拿工厂本身要加 & 前缀。

java
public interface FactoryBean<T> {
    T getObject() throws Exception;   // 真正暴露的产品
    Class<?> getObjectType();
    boolean isSingleton();
}

什么时候用:创建过程复杂、需要编码逻辑的对象。我接触最多的三个现成实现:

  • MyBatis 的 SqlSessionFactoryBean:解析 mapper XML、构建 SqlSessionFactory,纯声明配不出来,只能代码造
  • OpenFeign 的 FeignClientFactoryBean:@FeignClient 接口没有实现类,getObject() 里动态代理生成 HTTP 客户端——这就是"接口也能被注入"的原因
  • 老项目把第三方 SDK 客户端包成 FactoryBean 做初始化重试

和 @Bean 的选择:只是"构造一下"用 @Bean 方法就够;需要参与容器按类型/名字的按需触发、或要在 Bean 生命周期的特殊时点(如提前暴露给循环依赖)生成对象时才上 FactoryBean。

区分记忆:BeanFactory 是工厂(容器),FactoryBean 是"会下蛋的 Bean"。