FactoryBean 和 BeanFactory详解

REF mp.weixin.qq.com/s/SVdyZfjoM...

1. 核心角色与定义

  • BeanFactory:

    • 角色: IoC 容器的根接口
    • 定义: 它是 Spring IoC 容器最基础、最底层的接口。它定义了容器管理 Bean 的核心方法 ,例如:
      • getBean(String name): 根据名称获取 Bean 实例。
      • getBean(Class<T> requiredType): 根据类型获取 Bean 实例。
      • containsBean(String name): 判断容器是否包含指定名称的 Bean。
      • isSingleton(String name): 判断指定名称的 Bean 是否是单例。
      • getType(String name): 获取指定名称 Bean 的类型。
      • getAliases(String name): 获取指定名称 Bean 的别名。
    • 本质: 它是一个对象工厂 ,负责存储、管理和提供 Bean 实例 。它是 Spring IoC 容器功能的基础骨架。我们通常使用的 ApplicationContext (如 ClassPathXmlApplicationContext, AnnotationConfigApplicationContext) 是 BeanFactory高级子接口,提供了更多企业级功能(如事件发布、国际化、资源访问等)。
  • FactoryBean:

    • 角色: 创建复杂对象的特殊 Bean
    • 定义: 它是一个接口 ,实现该接口的类本身是一个被 Spring 管理的 Bean 。但这个 Bean 的主要职责不是提供自身实例,而是负责创建并返回另一个特定类型的对象
    • 核心方法:
      • T getObject()最重要 的方法。实现此方法创建并返回目标对象实例 。这个对象才是最终需要被注入或通过 getBean() 获取到的对象。
      • Class<?> getObjectType(): 返回 getObject() 方法所创建对象的类型。
      • boolean isSingleton(): 指示 getObject() 返回的对象是否是单例。通常返回 true
    • 本质: 它是一种生产机制 ,封装了创建复杂、有状态、需要特殊初始化逻辑或难以直接通过简单构造创建的对象的逻辑。它本身也是一个 Bean,但其价值在于它生产的产品。

2. 关键区别总结

特性 BeanFactory FactoryBean
核心角色 IoC 容器本身 (容器根接口) 特殊 Bean (对象工厂)
作用 管理所有 Bean 的生命周期、依赖注入和提供 封装复杂对象的创建逻辑,生产另一个对象
本质 容器 / 对象仓库 / 管理者 生产者 / 工厂 (本身也是被管理的 Bean)
目标对象 直接管理并暴露 Bean 实例 通过 getObject() 方法暴露其创建的目标对象实例
获取方式 getBean("beanName") 直接获取目标 Bean 实例 getBean("&factoryBeanName") 获取 FactoryBean 本身 getBean("factoryBeanName") 获取 FactoryBean 创建的目标对象
使用场景 任何需要 Spring IoC 容器管理 Bean 的场景 创建需要复杂初始化、依赖外部资源、代理对象、集成第三方库对象(如 SqlSessionFactory)等场景
类比 超级工厂,管理所有生产线和产品仓库 工厂中的一条特殊生产线,专门生产某种复杂产品

3. 使用方式与示例

  • BeanFactory 使用:

    • 通常不直接使用 BeanFactory 接口,而是使用其增强子接口 ApplicationContext
    • 通过 ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);new ClassPathXmlApplicationContext("applicationContext.xml"); 启动容器。
    • 通过 ctx.getBean(MyService.class)ctx.getBean("myService") 获取 Bean 实例。
  • FactoryBean 使用:

    • 步骤 1: 创建一个类实现 FactoryBean<T> 接口 (T 是目标对象类型)。

    • 步骤 2: 实现 getObject(), getObjectType(), isSingleton() 方法。

    • 步骤 3: 将这个实现类作为一个普通的 Bean 注册到 Spring 容器中(通过 @Bean, @Component, XML <bean> 等)。

    • 示例: 创建一个生产 Connection 对象的 ConnectionFactoryBean (简化示例):

      java 复制代码
      public class ConnectionFactoryBean implements FactoryBean<Connection> {
      
          private String url;
          private String username;
          private String password;
      
          // ... setters for properties ...
      
          @Override
          public Connection getObject() throws Exception {
              // 复杂的连接创建和初始化逻辑
              return DriverManager.getConnection(url, username, password);
          }
      
          @Override
          public Class<?> getObjectType() {
              return Connection.class;
          }
      
          @Override
          public boolean isSingleton() {
              return false; // 通常数据库连接不是单例
          }
      }
    • 注册: (假设使用 Java Config)

      java 复制代码
      @Configuration
      public class AppConfig {
          @Bean
          public ConnectionFactoryBean dataSourceConnection() {
              ConnectionFactoryBean factory = new ConnectionFactoryBean();
              factory.setUrl("jdbc:mysql://localhost:3306/mydb");
              factory.setUsername("root");
              factory.setPassword("secret");
              return factory;
          }
      }
    • 获取:

      java 复制代码
      ApplicationContext ctx = ...;
      // 获取 FactoryBean 创建的目标对象 (Connection)
      Connection conn = ctx.getBean("dataSourceConnection"); // 注意:bean name 是注册的 FactoryBean 的名字
      // 获取 FactoryBean 本身
      ConnectionFactoryBean factoryBean = ctx.getBean("&dataSourceConnection"); // 注意:加 '&' 前缀

4. 常见应用场景

  • BeanFactory:
    • 所有需要 Spring IoC 容器进行依赖注入、Bean 生命周期管理的场景。
    • 框架扩展的基础(如集成其他容器)。
  • FactoryBean:
    • 集成第三方库: 将非 Spring 管理的对象(如 MyBatis 的 SqlSessionFactory, Hibernate 的 SessionFactory, JPA 的 EntityManagerFactory)包装成 Spring Bean 的标准方式。Spring 通常提供现成的 FactoryBean 实现 (如 SqlSessionFactoryBean)。
    • 创建代理对象: 如 AOP 代理、事务代理。ProxyFactoryBean 是 Spring AOP 的核心类之一。
    • 创建有复杂初始化逻辑的对象: 对象创建需要多步操作、依赖外部资源(文件、网络)、异常处理等。
    • 创建遗留代码或难以修改代码的对象: 当无法直接在目标类上添加 @Component 或修改其构造方法时。
    • 创建需要动态决定实现的对象: 根据配置或运行时环境返回不同的具体实现。
    • 创建对象池: 管理可重用的对象实例。

5. 关键点与注意事项

  1. 名称相似,本质不同: 这是最大的混淆点。BeanFactory 是容器,FactoryBean 是容器中一个特殊的"工人"(Bean)。
  2. getBean() 的行为: 对注册的 FactoryBean 的 bean name (例如 "myFactoryBean") 调用 getBean()
    • ctx.getBean("myFactoryBean") -> 返回 FactoryBean.getObject() 方法创建的对象(目标对象)。
    • ctx.getBean("&myFactoryBean") -> 返回 FactoryBean 实例本身。& 前缀是获取 FactoryBean 本身的关键
  3. 间接性: FactoryBean 在容器和最终的目标对象之间增加了一层间接性。容器直接管理的是 FactoryBean 实例,而目标对象是由 FactoryBean 创建并间接提供的。
  4. ApplicationContext 自动检测: ApplicationContext 会自动检测所有实现了 FactoryBean 接口的 Bean,并在适当的时候调用其 getObject() 方法来获取目标对象。
  5. 配置简化: FactoryBean 极大地简化了在 Spring 配置中创建复杂对象的流程,将复杂的创建逻辑封装在 Java 代码中,配置只需要关注 FactoryBean 本身的属性设置。

总结

  • BeanFactory 是 Spring IoC 容器的基石。 它是管理者 ,定义了容器如何存储、管理和提供所有 Bean 的核心契约。它是"大工厂"。
  • FactoryBean 是用于创建特定复杂对象的特殊 Bean。 它是生产者 ,本身是一个被容器管理的 Bean,但其核心价值在于它实现了 getObject() 方法来制造另一个对象 。它是"工厂中的特殊生产线"。

理解 FactoryBeanBeanFactory 的区别对于深入掌握 Spring 的 IoC 机制、理解 Spring 如何集成第三方库以及处理复杂对象的创建至关重要。记住 & 前缀的用法是区分获取 FactoryBean 本身和其生产的目标对象的关键。

相关推荐
kangkang-1 小时前
PC端基于SpringBoot架构控制无人机(二):MavLink协议
java·spring boot·后端·无人机
麦兜*2 小时前
Spring Boot秒级冷启动方案:阿里云FC落地实战(含成本对比)
java·spring boot·后端·spring·spring cloud·系统架构·maven
喷火龙8号2 小时前
MSC中的Model层:数据模型与数据访问层设计
后端·架构
5ycode2 小时前
dify项目结构说明与win11本地部署
后端·开源
LaoZhangAI3 小时前
GPT-image-1 API如何传多图:开发者完全指南
前端·后端
fouryears_234173 小时前
深入拆解Spring核心思想之一:IoC
java·后端·spring
codervibe3 小时前
从 0 到 1,我如何独立开发一套教务系统(EduCore)
后端
error_cn3 小时前
podman安全性设置
后端
一个热爱生活的普通人3 小时前
Go 泛型终极指南:告别 interface{},写出更安全、更强大的代码!
后端·go
求知摆渡3 小时前
从零开始搭建typecho
前端·后端