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

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.xdnf.cn/news/16461.html

相关文章:

  • GPT 生成一个打字练习页面
  • 基于LNMP架构的分布式个人博客搭建
  • Mysql中的索引详解
  • 浅谈智能体经济(上篇)——人机共生、生态自治的未来经济形态
  • JavaScript单线程实现异步
  • 「iOS」————MRC
  • Python爬虫实战:研究netaddr库相关技术构建IP地址信息采集分析系统
  • 【NLP实践】三、LLM搭建中文知识库:提供RestfulAPI服务
  • 解决GoLand运行go程序报错:Error: Cannot find package xxx 问题
  • 3.JDK+JRE组件构成与协作
  • Qt 窗口 工具栏QToolBar、状态栏StatusBar
  • Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现标签条码一维码的检测(C#代码,UI界面版)
  • 基于Django的天气数据可视化分析预测系统
  • 背包DP之多重背包
  • python 阿里云 安装 dashscope的简介、安装
  • 【数据结构与算法】数据结构初阶:详解排序(二)——交换排序中的快速排序
  • 算法竞赛阶段二-数据结构(36)数据结构双向链表模拟实现
  • bash的特性-bash中的引号
  • 力扣131:分割回文串
  • 智能化设备健康管理:中讯烛龙预测性维护系统引领行业变革
  • 零基础,如何入手学习SAP?
  • ASP.NET Core 高并发万字攻防战:架构设计、性能优化与生产实践
  • OpenLayers 综合案例-地图绘制
  • 使用低级上位画图法理解在对磁盘空间进行容量分配时【低级单位上位至高级单位的换算】
  • 【论文阅读】ON THE ROLE OF ATTENTION HEADS IN LARGE LANGUAGE MODEL SAFETY
  • Flutter开发实战之CI/CD与发布流程
  • Unity SMAA
  • 结合Golang语言说明对多线程编程以及 select/epoll等网络模型的使用
  • 携带参数的表单文件上传 axios, SpringBoot
  • 从零开始:Coze Studio开源版部署全记录(win11)