《SpringBoot 3:入门与应用实战》第 3 章 IOC 容器中的 Bean 阅读笔记 1
《SpringBoot 3入门与应用实战》第 3 章 IOC 容器中的 Bean 阅读笔记 1IOC 容器中存放和管理的大多数是与程序运行相关的 Bean在 Spring Framework 中对象被统称为 Bean组件​即能被 Spring Framework 的 IOC 容器创建或管理的对象都可以称为 Bean组件​。通过编写 XML 配置文件或注解配置类将第三方框架的核心 API 注册为 IOC 容器中的 Bean这些核心 API 对象会在适当的位置发挥其作用以支撑项目的正常运行。一个 Bean 的定义中可以包含以下因素Bean 的 Name​Bean 的所属类/接口信息Bean的作用域单实例或多实例。Bean 内部的依赖关系即 Bean 的内部注入了哪些属性和其他 Bean。Bean 的实例化方式即由构造方法创建还是由工厂方法创建。Bean 的生命周期是否包含对象创建后的初始化动作和对象被回收前的销毁动作。Bean 和对象有什么区别在学习 Spring 时经常遇见 Bean 的概念Bean 和 Java 中的对象有什么区别。Bean 其实就是 Java 中的对象在 Spring Framework 中为了跟 Java new 出的对象区分把注入到 IOC 容器中的 Java 对象称为 Bean。Spring Framework 的核心特性之一就是 IOC 控制反转把创建和管理对象交给 Spring Framework 的 IOC 的容器我们直接使用 IOC 容器不用自己去创建和管理对象。3.1 Bean的类型在 Spring Framework 中Bean 有两种类型普通 Bean 和工厂 Bean (FactoryBean)。3.1.1 普通 Bean普通 Bean 的定义非常好理解第 2 章中的所有 Bean 都是普通 Bean包括使用 Component 注解及其派生注解标注的 Bean以及使用 标签、Bean 注解定义的 Bean。3.1.2 FactoryBean除了普通的 BeanSpring Framework 还考虑到特殊情况某些 Bean 的创建过程比较复杂使用 XML 配置文件或者注解声明较难甚至无法完成。因而引入了 FactoryBean 机制借助工厂方法创建 Bean 对象。1.理解 FactoryBeanFactoryBean 是一个接口如果某个类实现了 FactoryBean 接口它将不再是一个普通 Bean而是一个创建对象的工厂。2.FactoryBean 的使用通过简单示例演示 FactoryBean 的使用。假设小朋友要买玩具由玩具工厂给小朋友制造玩具。(1)声明小朋友玩具首先声明小朋友类 ChildChild类中添加一个 wantToy 的属性指代小朋友想买的玩具类别。之后我们再创建一个玩具的抽象类 Toy 和两个具体的子类球类 Ball 和玩具汽车类 Car。packagecom.yangjunbo.bean.examplea;publicclassChild{// 当前小朋友想玩球privateStringwantToyball;publicStringgetWantToy(){returnwantToy;}}packagecom.yangjunbo.bean.examplea;publicabstractclassToy{privateStringname;publicToy(Stringname){this.namename;}}packagecom.yangjunbo.bean.examplea;publicclassBallextendsToy{// 球publicBall(Stringname){super(name);}}packagecom.yangjunbo.bean.examplea;publicclassCarextendsToy{// 玩具汽车publicCar(Stringname){super(name);}}(2)声明玩具工厂接下来声明一个玩具工厂类 ToyFactoryBean使其实现 FactoryBean 接口并指定泛型为 Toy。由需求分析可知玩具工厂只有知道小朋友想买什么玩具才能对应地生产从代码逻辑上讲玩具工厂应当依赖小朋友由小朋友为它提供玩具类别由此可知 ToyFactoryBean 中应当注入 Child 对象。ToyFactoryBean 实现 FactoryBean 接口时需要至少实现两个方法包含生产目标对象的类型以及生产的逻辑。packagecom.yangjunbo.bean.examplea;importorg.springframework.beans.factory.FactoryBean;publicclassToyFactoryBeanimplementsFactoryBeanToy{privateChildchild;OverridepublicToygetObject()throwsException{switch(child.getWantToy()){caseball:returnnewBall(ball);casecar:returnnewCar(car);default:// Spring Framework 2.0开始允许返回null之前的1.x版本不允许returnnull;}}OverridepublicClassToygetObjectType(){returnToy.class;}publicvoidsetChild(Childchild){this.childchild;}}(3)注册玩具工厂使用注解配置类 BeanTypeConfiguration 将上述的 Child 和 ToyFactoryBean 注入到 IOC 容器中。packagecom.yangjunbo.bean.examplea;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;ConfigurationpublicclassBeanTypeConfiguration{BeanpublicChildchild(){returnnewChild();}BeanpublicToyFactoryBeantoyFactory(){ToyFactoryBeantoyFactorynewToyFactoryBean();toyFactory.setChild(child());returntoyFactory;}}(4)测试效果编写测试启动类 BeanTypeAnnoApplication使用 BeanTypeConfiguration 配置类驱动 IOC 容器并直接从容器中获取 Toy 对象。由于ToyFactoryBean 实现了 FactoryBean 接口在获取 Toy 对象时会触发 getObject 方法进而生成一个 Toy 对象。运行 main 方法之后控制台可以正确打印出 “ball”​证明 ToyFactoryBean 已经创建出了 Ball 对象。packagecom.yangjunbo.bean.examplea;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;publicclassBeanTypeAnnoApplication{publicstaticvoidmain(String[]args)throwsException{ApplicationContextctxnewAnnotationConfigApplicationContext(BeanTypeConfiguration.class);Toytoyctx.getBean(Toy.class);System.out.println(toy);}}3.FactoryBean 与 Bean 同时存在如果 IOC 容器中同时存在 FactoryBean 与对应目标类型的 Bean则最终效果如何为了验证该效果我们在 BeanTypeConfiguration 中使用 Bean 注解手动注册一个 Ball 对象。接下来不修改 BeanTypeAnnoApplication 启动类直接运行 main 方法可以发现控制台抛出 NoUniqueBeanDefinitionException 异常提示 IOC 容器中有两个 Toy 对象。由此得出一个结论FactoryBean 创建的 bean 对象会直接放在 IOC 容器中。如果修改一下 BeanTypeAnnoApplication 中 main 方法的代码将获取单个 Toy 对象改为获取全部 Toy 对象。重新运行 main 方法可以发现控制台打印了两个 toy通过 ToyFactoryBean 创建出来的 Ball 对象的名称叫 toyFactory。packagecom.yangjunbo.bean.examplea;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;ConfigurationpublicclassBeanTypeConfiguration{BeanpublicChildchild(){returnnewChild();}BeanpublicToyFactoryBeantoyFactory(){ToyFactoryBeantoyFactorynewToyFactoryBean();toyFactory.setChild(child());returntoyFactory;}BeanpublicBallball(){returnnewBall(ball);}}packagecom.yangjunbo.bean.examplea;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;importjava.util.Map;publicclassBeanTypeAnnoApplication{publicstaticvoidmain(String[]args)throwsException{ApplicationContextctxnewAnnotationConfigApplicationContext(BeanTypeConfiguration.class);//Toy toy ctx.getBean(Toy.class);//System.out.println(toy);MapString,Toytoysctx.getBeansOfType(Toy.class);toys.forEach((name,toy)-{System.out.println(toy name : name, toy.toString());});}}4.取出 FactoryBean 本体取出 FactoryBean 本体有两种方式第一种是使用 FactoryBean 的类型获取即 ctx.getBean(ToyFactoryBean.class)第二种是在 Bean 的 id 前面加一个 符号即 ctx.getBean(“toyFactory”)。packagecom.yangjunbo.bean.examplea;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;importjava.util.Map;publicclassBeanTypeAnnoApplication{publicstaticvoidmain(String[]args)throwsException{ApplicationContextctxnewAnnotationConfigApplicationContext(BeanTypeConfiguration.class);//Toy toy ctx.getBean(Toy.class);//System.out.println(toy);MapString,Toytoysctx.getBeansOfType(Toy.class);toys.forEach((name,toy)-{System.out.println(toy name : name, toy.toString());});System.out.println(ctx.getBean(ToyFactoryBean.class));System.out.println(ctx.getBean(toyFactory));}}5.FactoryBean 创建 Bean 的实例数FactoryBean 接口中有一个默认方法 isSingleton返回值默认为 true代表默认是单实例的。连续两次获取 Toy 对象并对比内存地址可以发现是同一个对象。如果在 ToyFactoryBean 中重写 isSingleton 方法并返回 false再连续两次获取 Toy 对象内存地址则不相同。packagecom.yangjunbo.bean.examplea;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;importjava.util.Map;publicclassBeanTypeAnnoApplication{publicstaticvoidmain(String[]args)throwsException{ApplicationContextctxnewAnnotationConfigApplicationContext(BeanTypeConfiguration.class);//Toy toy ctx.getBean(Toy.class);//System.out.println(toy);MapString,Toytoysctx.getBeansOfType(Toy.class);toys.forEach((name,toy)-{System.out.println(toy name : name, toy.toString());});System.out.println(ctx.getBean(ToyFactoryBean.class));System.out.println(ctx.getBean(toyFactory));System.out.println(ctx.getBean(toyFactory));System.out.println(ctx.getBean(toyFactory));}}packagecom.yangjunbo.bean.examplea;importorg.springframework.beans.factory.FactoryBean;publicclassToyFactoryBeanimplementsFactoryBeanToy{privateChildchild;OverridepublicToygetObject()throwsException{switch(child.getWantToy()){caseball:returnnewBall(ball);casecar:returnnewCar(car);default:// Spring Framework 2.0开始允许返回null之前的1.x版本不允许returnnull;}}OverridepublicClassToygetObjectType(){returnToy.class;}publicvoidsetChild(Childchild){this.childchild;}OverridepublicbooleanisSingleton(){returnfalse;}}6.FactoryBean 创建 Bean 的时机IOC 容器中的普通 Bean 都是随 IOC 容器的初始化而一并创建的那么 FactoryBean 与创建的目标对象是否同时创建我们可以在 Toy 和ToyFactoryBean 的内部声明无参构造方法并添加控制台打印。创建一个新的启动类 BeanTypeAnnoApplicationmain 方法中只有创建 ApplicationContext 一行代码运行main方法可以发现控制台只打印了 ToyFactoryBean 的初始化文字而 Toy 的初始化文字并没有被打印由此得出结论FactoryBean 本身的加载是随 IOC 容器的初始化时机一并创建的。控制台并没有打印 “生产了一个” name说明 FactoryBean 中要创建的 Bean 还没有被加载**由此也就得出另一个结论FactoryBean 生产Bean 的机制是延迟生产。**如果在初始化 ApplicationContext 后再获取 Toy 对象此时会打印“生产了一个 ball”​印证了刚才的结论。packagecom.yangjunbo.bean.exampleb;importorg.springframework.context.ApplicationContext;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;publicclassBeanTypeAnnoApplication{publicstaticvoidmain(String[]args)throwsException{ApplicationContextctxnewAnnotationConfigApplicationContext(BeanTypeConfiguration.class);ctx.getBean(Toy.class);}}7.BeanFactory 与 FactoryBean 的区别BeanFactorySpring Framework 中实现 IOC 的底层容器​。FactoryBean用于创建 Bean 的工厂 Bean适合用来创建一些初始化流程比较复杂的 Bean。

相关新闻

从零部署F1赛车数据分析环境:以诺里斯匈牙利杆位圈为例

从零部署F1赛车数据分析环境:以诺里斯匈牙利杆位圈为例

这次我们来看一个赛车模拟与数据分析项目,它聚焦于F1匈牙利大奖赛的虚拟杆位圈分析。这个项目的核心价值在于,它并非一个简单的视频回放,而是一个能够深度解析赛车数据、还原冠军圈速背后技术细节的工具或模拟环境。对于赛车爱好者、模拟器玩…

2026/10/23 7:00:01 阅读更多 →
Samsung K4T1G084QG-BCF7:1Gb DDR2 SDRAM扩展级温度技术规格与应用

Samsung K4T1G084QG-BCF7:1Gb DDR2 SDRAM扩展级温度技术规格与应用

K4T1G084QG-BCF7:三星1Gb G-die DDR2 SDRAM深度解析在DDR2 SDRAM的发展历程中,三星的G-die系列产品以其成熟的工艺和稳定的性能,为各类嵌入式应用提供了可靠的内存解决方案。K4T1G084QG-BCF7便是这一代产品的代表型号,它采用60-ba…

2026/10/27 19:24:37 阅读更多 →
AI Copilot for Incidents:构建智能故障处理副驾驶的工程实践

AI Copilot for Incidents:构建智能故障处理副驾驶的工程实践

在实际的软件开发和运维工作中,生产环境故障(Incident)的处理是压力最大、最考验团队协作和技术能力的环节。当监控告警响起,工程师们需要在信息混乱、时间紧迫的情况下,快速定位根因、执行补救措施并恢复服务。这个过…

2026/10/24 13:14:04 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/31 0:19:11 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/30 9:20:34 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/30 10:19:21 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/31 0:59:28 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/30 10:19:39 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/30 9:21:37 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/30 17:32:24 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/30 10:28:40 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/31 0:09:01 阅读更多 →