当前位置: 首页 > 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.dtcms.com/a/301248.html

相关文章:

  • Flutter中实现页面跳转功能
  • vulhub-red靶机攻略
  • 深度学习计算(深度学习-李沐-学习笔记)
  • IKAnalyzer分词插件使用方法
  • 第十八章:AI的“通感”:揭秘图、文、音的共同语言——CLIP模型
  • 图像智能识别(一)-Python方向
  • 嵌入式学习日志————对射式红外传感器计次
  • 「iOS」————ARC
  • MyBatis-Plus 条件构造器(Wrapper)全解析
  • docker in docker - 在docker容器中使用宿主机的docker
  • mac电脑安装docker图文教程
  • Java面试全栈通关:从微服务到AI的技术深度解析
  • [10月考试] C
  • Java面试全攻略:Spring生态与微服务架构实战
  • LangChain实现RAG
  • [2025CVPR-图象超分辨方向]DORNet:面向退化的正则化网络,用于盲深度超分辨率
  • 马尔可夫链
  • 设计模式(十三)结构型:代理模式详解
  • Python 使用 asyncio 包处理并 发(避免阻塞型调用)
  • 图像智能识别算法记录
  • 动态规划 (Dynamic Programming) 算法概念-Python示例
  • Leetcode——287. 寻找重复数
  • SignalR 全解析:核心原理、适用场景与 Vue + .NET Core 实战
  • 工业控制系统安全之 Modbus 协议中间人攻击(MITM)分析与防范
  • 全面理解JVM虚拟机
  • RS485转profinet网关如何让JRT激光测距传感器开启自动模式连续测量模式
  • 淘宝获取店铺订单信息操作指南
  • Python爬虫入门:从零开始抓取网页数据
  • 每日一讲——Podman
  • 分布式事务-MQ事务消息学习与落地方案