解锁ApplicationContext vs BeanFactory: 谁更具选择性?

目录

一、聚焦源码回顾

(一)源码分析和理解

(二)简短的回顾对比建议

二、ApplicationContext vs BeanFactory特性对比

(一)主要特性总结

(二)直接建议

三、案例简单说明

(一)加载少量的 Bean的案例

(二)简单的命令行工具:用于读取配置文件并生成报告

(三)启动时加载大量的配置信息,并且在运行时需要动态地获取一些 Bean


针对ApplicationContext和BeanFactory,在理解其源码后,那在开发过程中应该选用ApplicationContext还是BeanFactory哪个更合适呢?

一、聚焦源码回顾

聚焦源码回顾的意义在于深入理解框架的内部机制和设计思想。通过仔细研究源码,可以了解框架的实现细节、各个组件之间的交互关系以及解决问题的方法,也就有助于更好地利用框架的功能,解决实际的开发问题,并且能够更加灵活地进行定制和扩展。

(一)源码分析和理解

在 Spring  官方文档中中,虽然没有明确的建议说应该优先选择 ApplicationContext 还是 BeanFactory,但是可以通过文档中的描述来理解它们的区别和用途。我们之前对这两部分进行了重新的学习和总结,具体见如下表格:

具体博客总结直接学习链接

重看Spring聚焦BeanFactory分析

重看Spring聚焦BeanFactory分析-CSDN博客

重看Spring聚焦ApplicationContext分析

重看Spring聚焦ApplicationContext分析-CSDN博客

(二)简短的回顾对比建议

直接简短总结来看的话,可以这样对比一下:

  1. BeanFactory:Spring 框架的中心接口,提供了高级配置机制来管理任何类型的对象,主要作用是提供依赖注入和基本的对象生命周期管理功能。

  2. ApplicationContext:BeanFactory 的一个子接口,它扩展了 BeanFactory 的功能,提供了更多的企业级功能和特性。它是 Spring 的核心容器,用于加载应用程序的配置文件,并管理 Bean 的生命周期。

从简单的对比可以看出,ApplicationContext 提供了比 BeanFactory 更多的功能和特性,因此在实际开发中,通常优先选择 ApplicationContext。但具体选择取决于项目的需求和场景。

二、ApplicationContext vs BeanFactory特性对比

(一)主要特性总结

一个简单的表格,用于比较 ApplicationContextBeanFactory 的主要特性:

特性ApplicationContextBeanFactory
自动装配支持支持
延迟初始化支持部分支持,需要手动配置
国际化消息处理支持部分支持,需要手动配置
事件发布支持部分支持,需要手动配置
AOP 配置支持部分支持,需要手动配置
安全性配置支持部分支持,需要手动配置
嵌套 ApplicationContext支持部分支持,需要手动配置
Web 应用上下文支持部分支持,需要手动配置
缓存功能支持(如注解缓存)部分支持,需要手动配置
加载应用程序上下文的方式通过类路径、文件系统、Web 应用程序上下文等方式加载通过类路径、文件系统等方式加载
扩展点提供多个扩展点和插件接口,可轻松扩展其功能较少的扩展点,相对较难扩展功能
适用场景适用于大多数企业级应用开发,提供更多的功能和特性适用于简单的应用场景,对资源要求较低,不需要使用额外的功能和特性

(二)直接建议

从这个表格来看,ApplicationContext 显然提供了更多的功能和特性,而且更适合复杂的企业级应用开发。它提供了自动装配、延迟初始化、国际化消息处理、事件发布、AOP 配置等多种功能,同时支持多种加载应用程序上下文的方式,具有更强的灵活性和扩展性。

相比之下,BeanFactory 虽然也提供了基本的依赖注入和对象生命周期管理功能,但功能相对较少,适用于简单的应用场景或对资源要求较低的情况。

所以总的来说大家会更倾向于推荐使用 ApplicationContext,因为它提供了更丰富的功能和更多的特性,能够更好地满足现代企业级应用开发的需求。当然,在一些特定的情况下,如资源有限或者对功能要求不高的情况下,选择 BeanFactory 也是可以的,但通常情况下 ApplicationContext 是更好的选择。

三、案例简单说明

(一)加载少量的 Bean的案例

假设我们正在开发一个简单的命令行应用程序,该应用程序只需要加载少量的 Bean,并且对于额外的功能需求并不是很高。在这种情况下,选择 BeanFactory 可能更为合适。

假设我们的 beans.xml 文件位于类路径(classpath)下的 src/main/resources 目录下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义一个名为 "helloWorld" 的 Bean --><bean id="helloWorld" class="org.zyf.javabasic.spring.beanFactory.HelloWorld"/>
</beans>

xmlnsxsi:schemaLocation 是 XML 命名空间和模式位置,用于指定 XML 文件的命名空间和 XML Schema 的位置。这些是标准的 Spring XML 配置文件头部。该 XML 配置文件定义了一个名为 helloWorld 的 Bean,它是一个 HelloWorld 类型的对象,简单定义如下:

package org.zyf.javabasic.spring.beanFactory;/*** @program: zyfboot-javabasic* @description: HelloWorld* @author: zhangyanfeng* @create: 2024-04-13 13:03**/
public class HelloWorld {public void sayHello() {System.out.println("Hello, World!");}
}

现在我们测试验证如下:

package org.zyf.javabasic.spring.beanFactory;import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;/*** @program: zyfboot-javabasic* @description: 选择 BeanFactory 可能更为合适。* @author: zhangyanfeng* @create: 2024-04-13 12:59**/
@Log4j2
public class BeanFactoryBetterTest {public static void main(String[] args) {// 创建 BeanFactoryBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml"));// 获取 BeanHelloWorld helloWorld1 = (HelloWorld) beanFactory.getBean("helloWorld");// 使用 BeanhelloWorld1.sayHello();// 创建 ApplicationContextApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");// 获取 BeanHelloWorld helloWorld2 = (HelloWorld) context.getBean("helloWorld");// 使用 BeanhelloWorld2.sayHello();}
}

虽然我们可以使用 ApplicationContext 来达到同样的效果,但在这种简单的情况下,选择 BeanFactory 更为轻量级,不需要加载额外的功能和特性,更加简洁明了。

然而,如果应用程序的需求变得更加复杂,需要更多的功能和特性(如自动装配、事件发布、AOP 配置等),或者需要集成其他 Spring 框架或第三方框架,那么使用 ApplicationContext 将更为合适。

(二)简单的命令行工具:用于读取配置文件并生成报告

假设有一个简单的命令行工具,用于读取配置文件并生成报告。在这个工具中,我们可能只需要加载一些配置信息,而不需要使用 Spring 框架提供的更复杂的功能。在这种情况下,使用 BeanFactory 可能更为合适。

假设我们有一个简单的配置文件 report-config.xml,其中包含了一些报告生成的配置信息,如数据库连接信息、报告格式等。下面是一个简化的示例:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 数据库连接信息 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/zyf"/><property name="username" value="zyf"/><property name="password" value="Zyf76#56uhb&@sh%hd567ijhfg"/></bean><!-- 报告生成器 --><bean id="reportGenerator" class="org.zyf.javabasic.spring.beanFactory.ReportGenerator"><property name="dataSource" ref="dataSource"/><!-- 其他配置属性 --></bean>
</beans>

在这个示例中定义了一个 dataSource使用Spring提供的 DriverManagerDataSource 类来创建数据库连接。现在定义一个自定义的 ReportGenerator 类,用于生成报告:

package org.zyf.javabasic.spring.beanFactory;import org.springframework.jdbc.core.JdbcTemplate;import javax.sql.DataSource;/*** @program: zyfboot-javabasic* @description: 调用其方法来生成报告* @author: zhangyanfeng* @create: 2024-04-13 13:52**/
public class ReportGenerator {private DataSource dataSource;// setter 方法用于接收 dataSource 属性的注入public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;}public void generateReport() {// 使用 JdbcTemplate 连接数据库JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);// 查询数据库并生成报告String sql = "SELECT * FROM user20240413";jdbcTemplate.query(sql, (rs, rowNum) -> {String username = rs.getString("username");String email = rs.getString("email");System.out.println("Username: " + username + ", Email: " + email);return null;});System.out.println("Report generated successfully.");}
}

对于这样一个简单的命令行工具,我们可能只需要加载这些配置信息,然后创建一个 ReportGenerator 实例,并调用其方法来生成报告。在这种情况下,使用 BeanFactory 就足够了,因为我们不需要 Spring 提供的更多的高级功能,如自动装配、事件发布等。下面是一个使用 BeanFactory 的示例:

package org.zyf.javabasic.spring.beanFactory;import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;/*** @program: zyfboot-javabasic* @description: 简单的命令行工具* @author: zhangyanfeng* @create: 2024-04-13 13:55**/
public class ReportToolTest {public static void main(String[] args) {// 创建 BeanFactoryBeanFactory beanFactory = new XmlBeanFactory(
new ClassPathResource("report-config.xml"));// 获取 reportGenerator BeanReportGenerator reportGenerator = (ReportGenerator) beanFactory.getBean("reportGenerator");// 使用 reportGenerator 生成报告reportGenerator.generateReport();}
}

在这个示例中,我们使用 BeanFactory 来加载 report-config.xml 文件,并获取了一个 reportGenerator Bean。然后,我们使用这个 Bean 来调用 generateReport 方法来生成报告。

尽管我们也可以使用 ApplicationContext 来达到同样的效果,但在这种简单的情况下,选择 BeanFactory 更为轻量级和简洁。

(三)启动时加载大量的配置信息,并且在运行时需要动态地获取一些 Bean

假设我们有一个 Spring Boot 应用程序,该应用程序需要在启动时加载大量的配置信息,并且在运行时需要动态地获取一些 Bean,这些 Bean 的创建可能依赖于其他 Bean。在这种情况下,使用 ApplicationContext 会更加方便和灵活。

首先,我们可以将所有的配置信息(如商品信息、用户信息、库存信息等)存储在数据库中。然后,在应用程序启动时,我们使用 ApplicationContext 加载数据库配置,并将其转换为 Spring 的 Bean,并将这些 Bean 注册到应用程序的上下文中。

在用户下单时,我们可以通过 ApplicationContext 获取相应的 Bean(如商品信息、用户信息、库存信息等),并根据用户的选择生成订单。

package org.zyf.javabasic.spring.beanFactory;/*** @program: zyfboot-javabasic* @description: OrderService* @author: zhangyanfeng* @create: 2024-04-13 14:31**/
public class OrderService {private final ApplicationContext context;public OrderService(ApplicationContext context) {this.context = context;}public void placeOrder(String productId, String userId) {// 根据商品 ID 获取商品信息Product product = context.getBean(ProductRepository.class).findById(productId);// 根据用户 ID 获取用户信息User user = context.getBean(UserRepository.class).findById(userId);// 根据商品 ID 获取库存信息Inventory inventory = context.getBean(InventoryService.class).getInventory(productId);// 检查库存是否充足if (inventory.getQuantity() > 0) {// 生成订单逻辑Order order = new Order(user, product);// 省略生成订单的逻辑System.out.println("Order placed successfully.");} else {System.out.println("Insufficient inventory.");}}
}

在这个例子中,OrderService 类使用 ApplicationContext 来获取商品信息、用户信息和库存信息,并根据这些信息生成订单。通过使用 ApplicationContext,我们可以在运行时动态地获取所需的 Bean,并且不需要在代码中硬编码 Bean 的依赖关系。

总的来说,使用 ApplicationContext 可以使应用程序更加灵活,并且可以在运行时动态地管理和获取 Bean,从而使应用程序更加易于扩展和维护。

文章推荐阅读

在程序员的职业规划中,成为软件架构师是一个非常有吸引力的选择。但是对于如何才能成为一名架构师,不少同学认为只要代码写得好,就能得到公司提拔,晋升为架构师。

还真不是这样的,如果不具备架构思维,即使代码能写到极致,在开展工作时也将不可避免地掉到坑里去。例如,看起来面面俱到的设计,但因为太复杂而无法落地;错估需求,导致高射炮打蚊子,浪费资源;实现方案总想毕其功于一役,结果需求变化就要推倒重来。

所以程序员要清醒地认识到,写好代码仅是软件开发过程中的一个环节,把代码写到极致也不会自动成为架构师。架构工作贯穿了软件生命周期,做好架构一定要学会架构思维

有一本书专门告诉程序员如何培养架构思维——《架构思维:从程序员到CTO》。本书以架构师工作中的痛点问题为导向,结合大量真实、复杂的案例,帮助架构师建立起思考框架,提高架构设计能力,规划职业成长路径。

具体链接如下:

https://item.jd.com/14019725.html

一本书揭秘程序员如何培养架构思维!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/2277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenTelemetry-1.介绍

目录 1.是什么 2.为什么使用 OpenTelemetry 3.数据类型 Tracing Metrics Logging Baggage 4.架构图 5.核心概念 6.相关开源项目 ​编辑 7.分布式追踪的起源 8.百花齐放的分布式追踪 Zipkin Skywalking Pinpoint Jaeger OpenCensus OpenTracing 9.Openteleme…

虚假新闻检测——Adapting Fake News Detection to the Era of Large Language Models

论文地址&#xff1a;https://arxiv.org/abs/2311.04917 1.概论 尽管大量的研究致力于虚假新闻检测&#xff0c;这些研究普遍存在两大局限性&#xff1a;其一&#xff0c;它们往往默认所有新闻文本均出自人类之手&#xff0c;忽略了机器深度改写乃至生成的真实新闻日益增长的现…

【漏洞复现】Adobe ColdFusion 任意文件读取漏洞 CVE-2024-20767

漏洞描述 Adobe ColdFusion是美国奧多比(Adobe)公司的一套快速应用程序开发平台。该平台ColdFusion 2023 <= Update 6 和 ColdFusion 2021<= Update 12版本中存在一个任意文件读取漏洞。 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共…

【北京迅为】《iTOP-3588开发板系统编程手册》-第20章 socket 应用编程

RK3588是一款低功耗、高性能的处理器&#xff0c;适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用&#xff0c;RK3588支持8K视频编解码&#xff0c;内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

TI_DSP_F2808学习笔记1: GPIO

1. 初始化设置 1.1 控制寄存器 GPxMUX功能选择寄存器/多功能复用选择 GPxDIR 方向选择寄存器/输入输出选择 0 输入 1 输出GPxPUD 上拉功能选择寄存器/是否启用内部上拉 0 有上拉&#xff0c;1禁止上拉GPxQSeln输入限定选择寄存器 输入n次为0或1才有效&#xff0c;滤波 1.2 数…

使用nacos分布式配置的好处!!!

1、没使用nacos之前&#xff0c;我们如果修改了配置文件&#xff0c;就必须重新发布应用&#xff0c;配置才会生效。使用nacos远程配置后&#xff0c;配置就可以实时更新&#xff0c;就无需重新发布应用&#xff0c;减少了重新发布所消耗的时间&#xff0c;提高了效率。 2、可…

ffmpeg截图(关键帧截图)

1.rtsp流截图 ffmpeg --stimeout 1000000 -rtsp_transport tcp -i rtsp://xxx -vf selecteq(pict_type,PICT_TYPE_I) -vsync vfr -ss 00:00:00.000 -vframes 1 -s 640x480 -y output.jpg -hide_banner参数解释&#xff1a; ● -stimeout 1000000&#xff1a;设置socket超时时间…

PDF 书签制作与调整

本文是对以前发表的旧文拆分&#xff0c;因为原文主题太多&#xff0c;过长&#xff0c;特另起一篇分述。 第一部分 由可编辑 PDF 文档创建书签 方法 1. Adobe Acrobat Pro autobookmark AutoBookmark 是一个可用于 Adobe Acrobat 自动生成书签的插件。 官方下载地址&…

corona渲染器锐化模糊设置,corona高效出图方法

​在使用Corona渲染器进行效果图渲染时&#xff0c;锐化和模糊是两种常用的设置&#xff0c;它们主要用于调整图像的清晰度和柔化效果。锐化参数可以增强图像中的细节&#xff0c;使画面看起来更加清晰锋利&#xff1b;而模糊参数则可以用来柔化图像边缘&#xff0c;减少图像噪…

Etsy多账号关联怎么办?Etsy店铺防关联解决方法

Etsy虽然相对于其他跨境电商平台来说比较小众&#xff0c;但因为平台是以卖手工艺品为主的&#xff0c;所以成本较低&#xff0c;利润很高。许多跨境卖家都纷纷入驻&#xff0c;导致平台规则越发严格&#xff0c;操作不当就会封号&#xff0c;比如一个卖家操作多个账号会出现关…

10.接口自动化测试学习-Pytest框架(2)

1.mark标签 如果在每一个模块&#xff0c;每一个类&#xff0c;每一个方法和用例之前都加上mark标签&#xff0c;那么在pytest运行时就可以只运行带有该mark标签的模块、类、接口。 这样可以方便我们执行自动化时&#xff0c;自主选择执行全部用例、某个模块用例、某个流程用…

二分查找知识点及练习题

知识点讲解 一、没有相同元素查找 请在一个有序递增数组中&#xff08;不存在相同元素&#xff09;&#xff0c;采用二分查找&#xff0c;找出值x的位置&#xff0c;如果x在数组中不存在&#xff0c;请输出-1&#xff01; 输入格式 第一行&#xff0c;一个整数n&#xff0c;代…

家用洗地机买什么牌子的好?四大业内顶尖品牌推荐

家庭清洁一直是必不可少的&#xff0c;但用传统的手动拖地清洁&#xff0c;费时又费力。现在出现了洗地机&#xff0c;确实改变了我们对家庭清洁的看法。它不仅能扫地、拖地&#xff0c;还能吸水&#xff0c;甚至能够自动清洁滚刷解放我们双手&#xff0c;提供高效清洁的同时还…

flutter 点击按钮限流方案

文章目录 前言一、理解限流的思想二、flutter实现代码如下&#xff1a;总结 前言 最近写flutter项目&#xff0c;遇到提交表单重复点击问题&#xff0c;下面是解决方案&#xff0c;希望帮助到大家。 一、理解限流的思想 1、限流思想 限流&#xff08;Throttle&#xff09; 限…

【Linux系列】 离线安装vnc 可视化桌面

离线安装vnc 可视化桌面 缘下载安装vnc初始化链接 缘 项目需要下载 下载地址&#xff1a; http://mirror.centos.org/centos/7/updates/x86_64/Packages/tigervnc-license-1.8.0-31.el7_9.noarch.rpm http://mirror.centos.org/centos/7/os/x86_64/Packages/libXfont2-2.0.…

【Day 6】MySQL 基础

1 MySQL DataBase&#xff08;DB&#xff09;是存储和管理数据的仓库 DataBaseManagementSystem&#xff08;DBMS&#xff09;数据库管理系统&#xff0c;操纵和管理数据库的大型软件 SOL&#xff08;Structured QueryLanguage&#xff09;操作关系型数据库的编程语言&#…

C++/Qt 小知识记录5

工作中遇到的一些小问题&#xff0c;总结的小知识记录&#xff1a;C/Qt 小知识5 Windows下查看端口占用情况C调用Python三方库测试库有没有被加上的测试方法初始化使用Python的env环境&#xff0c;用Py_SetPythonHome设置GDAL相关的&#xff0c;需要把osgeo、rasterio的路径加入…

轻松了解深度学习的几大模型

1. 前馈神经网络&#xff08;Feedforward Neural Networks, FNNs&#xff09; 想象一下&#xff0c;你有一堆不同颜色的球&#xff0c;你的任务是将它们分类到对应的颜色盒子里。你可能会观察每个球的颜色&#xff0c;然后决定它应该放在哪里。这个过程就像是前馈神经网络的工…

【iOS开发】(一)2024 从一无所有开始,到ios开发(react Native)

​ 2024 从一无所有开始&#xff0c;到ios开发&#xff08;react Native&#xff09; 目录标题 1 工具简介2 基础环境搭建1 安装 brew2 安装 Node.js3 安装 Yarn4 安装 React Native 脚手架 3 ios环境搭建4创建并启动一个app 在这里插入图片描述 1 工具简介 Homebrew (brew)&a…

OpenHarmony实战开发-页面布局检查器ArkUI Inspector使用指导

DevEco Studio内置ArkUI Inspector工具&#xff0c;开发者可以使用ArkUI Inspector&#xff0c;在DevEco Studio上查看应用在真机上的UI显示效果。利用ArkUI Inspector工具&#xff0c;开发者可以快速定位布局问题或其他UI相关问题&#xff0c;同时也可以观察和了解不同组件之间…