当前位置: 首页 > news >正文

Spring经典“送命题”:BeanFactory vs FactoryBean

图片

故事场景:魔法玩具作坊

BeanFactory — 玩具作坊本身

BeanFactory(或者我们更常用的ApplicationContext)就是整个玩具作坊

  • • 它的身份:是老板,是管理者,是整个生产线的总和。它是容纳一切的容器

  • • 它的工作:作坊的货架上陈列着各种可以直接生产的玩具,比如“泰迪熊”、“积木块”等(普通的Bean)。

  • • 互动方式:你作为顾客,走到作坊的前台(调用context.getBean(...)),对老板说:“给我来一个‘泰迪熊’”。老板(BeanFactory)就会启动标准生产线,给你造一个泰迪熊。

BeanFactory 是提供产品(Bean)的工厂

FactoryBean — 作坊里的一台“多功能3D打印机”

现在,作坊里引进了一台非常神奇、非常复杂的“多功能3D打印机”(FactoryBean)。

  • • 它的身份:它不是老板,它只是作坊里众多设备中的一台。它本身也是一个需要被老板管理和维护的“资产”(它本身也是一个Bean)。

  • • 它的特殊工作:这台3D打印机的唯一目的,就是生产其他更复杂的玩具,比如“变形金刚”。制造“变形金刚”的工艺太复杂了,标准生产线做不了,必须由这台3D打印机来定制生产。

  • • 神奇的互动方式

    1. 1. 当你想要“变形金刚”时 (context.getBean("transformerPrinter")):
      你走到前台,对老板说:“你好,我想要一台‘变形金刚’”。老板知道,“变形金刚”是由那台特殊的3D打印机(bean id为transformerPrinter)生产的。
      老板并不会把那台沉重的3D打印机推给你
      相反,他会走到3D打印机前,按下“打印”按钮(调用getObject()方法)。机器一通操作后,一个崭新的“变形金刚”被生产出来。老板会把这个**“变形金刚”玩具(getObject()返回的对象)**交给你。

    2. 2. 当你想要“3D打印机”本身时 (context.getBean("&transformerPrinter")):
      有一天,这台3D打印机坏了,你需要找个维修工来修。这时你走到前台,对老板说出了一句“暗号”:“你好,我要找的不是打印出来的玩具,而是那台ID前面带‘&’符号的‘&transformerPrinter’设备本身!
      老板听到暗号后,明白了你的意图,于是他不会去按打印按钮,而是会带你到后台,让你看到这台3D打印机本身(FactoryBean实例)

故事总结:

特性

BeanFactory

 (玩具作坊)

FactoryBean

 (3D打印机)

本质容器

 (Container)。Spring IoC的基础设施

Bean

。一个实现了特定接口的特殊Bean

角色工厂

。负责生产和管理所有的Bean。

工厂 Bean

。一个能生产其他对象的Bean。

getBean("id") 返回

返回id对应的Bean实例。

返回该FactoryBean生产的对象 (调用getObject()的结果)。

getBean("&id") 返回

(无此用法)

返回该FactoryBean实例本身

核心比喻整个玩具作坊作坊里的一台“玩具制造机”
一句话总结我是Spring的心脏,是所有Bean的妈。我是一个特殊的Bean,我的工作是当另一个对象的妈。

结论:
BeanFactory是Spring框架的根基,是管理者。而FactoryBean是一种由你编写的、用于封装复杂对象创建逻辑的、被BeanFactory所管理的特殊Bean。一个FactoryBean活在BeanFactory之中。


代码示例

// We'll use a simple Spring Boot setup for demonstration.
// File: Application.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@SpringBootApplication
public class FactoryDemoApplication {public static void main(String[] args) {// ApplicationContext IS-A BeanFactory. It's our container.ApplicationContext context = SpringApplication.run(FactoryDemoApplication.class, args);System.out.println("--- 演示 BeanFactory (容器) 的基本作用 ---");// We ask the container (BeanFactory) for a regular bean.String myMessage = context.getBean("myMessage", String.class);System.out.println("From BeanFactory, got myMessage: " + myMessage);System.out.println("\n--- 演示 FactoryBean 的特殊作用 ---");// 1. 获取由 FactoryBean 创建的对象// We ask for the bean named "myTool". Spring sees it's a FactoryBean.// It DOES NOT return the ToolFactoryBean instance.// Instead, it calls toolFactoryBean.getObject() and returns the result.Object toolObject = context.getBean("myTool");System.out.println("getBean(\"myTool\") 返回的对象类型: " + toolObject.getClass().getName()); // Will be com.example.Tool// 2. 获取 FactoryBean 本身// If we really want the factory itself, we must prefix the name with '&'.Object factoryObject = context.getBean("&myTool");System.out.println("getBean(\"&myTool\") 返回的对象类型: " + factoryObject.getClass().getName()); // Will be com.example.ToolFactoryBean}
}// File: AppConfig.java
@Configuration
class AppConfig {@Beanpublic String myMessage() {return "Hello from a simple bean!";}@Beanpublic ToolFactoryBean myTool() {return new ToolFactoryBean();}
}// File: Tool.java (The object we want the factory to produce)
import org.springframework.stereotype.Component;class Tool {private String name = "Screwdriver";public Tool() {System.out.println("A new Tool object has been created!");}// getters and setters...
}// File: ToolFactoryBean.java (The special factory bean)
import org.springframework.beans.factory.FactoryBean;class ToolFactoryBean implements FactoryBean<Tool> {@Overridepublic Tool getObject() throws Exception {// This is where the custom, complex object creation logic would go.System.out.println("ToolFactoryBean's getObject() is called. Creating and returning a Tool.");return new Tool();}@Overridepublic Class<?> getObjectType() {return Tool.class;}@Overridepublic boolean isSingleton() {return true;}
}

http://www.lryc.cn/news/601318.html

相关文章:

  • 力扣131:分割回文串
  • JavaScript单线程实现异步
  • 探秘CommonJS:Node.js模块化核心解析
  • GPT-4o实战应用指南:从入门到精通的技术心得
  • 物联网安装调试-物联网网关
  • 【图像处理基石】Segment Anything Model (SAM) 调研
  • MGRE综合实验
  • 望言OCR视频字幕提取2025终极评测:免费版VS专业版提全方位对比(含免费下载)
  • 20250707-2-Kubernetes 网络-Ingress暴露应用(http与https)_笔记
  • Flutter中实现页面跳转功能
  • iOS安全和逆向系列教程 第21篇:iOS应用加密与混淆技术深度剖析
  • macOS配置 GO语言环境
  • mac电脑安装docker图文教程
  • 智慧施工:施工流程可视化管理系统
  • 【秋招笔试】7月26日科大讯飞秋招第二题
  • 算法竞赛阶段二-数据结构(37)数据结构动态链表list
  • DDPM:重新定义图像生成的革命性技术
  • Ubuntu Linux 如何配置虚拟内存 —— 一步一步配置 Ubuntu Server 的 NodeJS 服务器详细实录8
  • RabbiteMQ安装-ubuntu
  • Android CameraX 使用指南:简化相机开发
  • Keepalived + LVS-DR 高可用与负载均衡实验
  • ubuntu 部署 coze-loop
  • [10月考试] F
  • Java 后端 Cookie Session Token会话跟踪技术
  • LabelMe数据标注软件介绍和下载
  • cmake入门学习
  • VScode 支持 QNX 源码跳转
  • JavaWeb(苍穹外卖)--学习笔记13(微信小程序开发,缓存菜品,Spring Cache)
  • 中级全栈工程师笔试题
  • JavaScript数组去重性能优化:Set与Object哈希表为何效率最高