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

news2024/11/16 3:36:12

目录

一、聚焦源码回顾

(一)源码分析和理解

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

二、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/beans
                           http://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) {
        // 创建 BeanFactory
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml"));

        // 获取 Bean
        HelloWorld helloWorld1 = (HelloWorld) beanFactory.getBean("helloWorld");

        // 使用 Bean
        helloWorld1.sayHello();


        // 创建 ApplicationContext
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        // 获取 Bean
        HelloWorld helloWorld2 = (HelloWorld) context.getBean("helloWorld");

        // 使用 Bean
        helloWorld2.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/beans
                           http://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) {
        // 创建 BeanFactory
        BeanFactory beanFactory = new XmlBeanFactory(
new ClassPathResource("report-config.xml"));

        // 获取 reportGenerator Bean
        ReportGenerator 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.coloradmin.cn/o/1611387.html

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

相关文章

21.组件组成

组件组成 组件最大的优势就是可复用性 当使用构建步骤时&#xff0c;我们一般会将 Vue 组件定义在一个单独的 .vue 文件中&#xff0c;这被叫做单文件组件(简称 SFC) 组件组成结构 <template><div>承载标签</div> </template> <script> expor…

矽塔SA8321 单通道 2.7-12.0V 持续电流 3.0A H 桥驱动芯片

描述 SA8321是为消费类产品&#xff0c;玩具和其他低压或者电池供电的运动控制类应用提供了一个集成的电机驱动器解决方案。此器件能够驱动一个直流无刷电机&#xff0c;由一个内部电荷泵生成所需的栅极驱动电压电路和4个功率 NMOS组成H桥驱动&#xff0c;集成了电机正转/反…

【ThinkPHP框架教程·Part-01】ThinkPHP6.x框架安装教程

文章目录 一、框架介绍1、框架简介和版本选择2、主要新特性 二、安装步骤1、下载并运行Composer-Setup.exe2、安装TP前切换镜像3、安装稳定版4、测试运行 一、框架介绍 1、框架简介和版本选择 Thinkphp是一种基于php的开源web应用程序开发框架ThinkPHP框架&#xff0c;是免费开…

封装个js分页插件

// 分页插件类 class PaginationPlugin {constructor(fetchDataURL, options {}) {this.fetchDataURL fetchDataURL;this.options {containerId: options.containerId || paginationContainer,dataSizeAttr: options.dataSizeAttr || toatalsize, // 修改为实际API返回的数据…

easyx库的学习(文字绘制)

前言 昨天刚刚写完了基本图形的制作&#xff0c;今天直接可以来看看&#xff0c;在easyx中使用文字 直接看代码吧 文字绘制 void drawTest() {printf("hello,EasyX");//指的是在控制台打印//设置字体大小&#xff0c;样式settextstyle(30, 0, "微软雅黑&quo…

二维码门楼牌管理应用平台建设:核实与审核的关键作用

文章目录 前言一、二维码门楼牌管理应用平台的建设背景二、核实与审核在二维码门楼牌管理中的应用三、核实与审核的重要性四、优化建议 前言 随着信息技术的快速发展&#xff0c;二维码门楼牌管理应用平台在社区管理中发挥着越来越重要的作用。本文将深入探讨该平台建设过程中…

数据结构––kmp算法(串)

kmp算法作为串的一个重要内容&#xff0c;必然有一定的难度&#xff0c;而在看到各类教辅书里的概念与解释后&#xff0c;其晦涩难懂的内容直接劝退一部分人&#xff0c;现在&#xff0c;让我们来看看吧 KMP解决的问题类型 KMP算法的作用就是在一个已知的字符串中查找子串的位…

一次Redis访问超时的“捉虫”之旅

01 引言 作为后端开发人员&#xff0c;对Redis肯定不陌生&#xff0c;它是一款基于内存的数据库&#xff0c;读写速度非常快。在爱奇艺海外后端的项目中&#xff0c;我们也广泛使用Redis&#xff0c;主要用于缓存、消息队列和分布式锁等场景。最近在对一个老项目使用的docker镜…

HTML、CSS常用的vscode插件 +Css reset 和Normalize.css

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 ✍HTML、CSS常用的vscode插件&#x1f34e;1 HTML 标签同步重命名 – Auto Re…

ardunio中自定义的库文件

1、Arduino的扩展库都是放在 libraries目录下的。完整路径为&#xff1a;C:\Users\41861\AppData\Local\Arduino15\libraries 所以我们需要在这个目录下创建一个文件夹&#xff0c;比如上面的例子是esp32上led灯控制程序&#xff0c;于是我创建了 m_led文件夹&#xff08;前面加…

音视频封装格式解析(1)——H264格式简析,I/P/B帧是什么?H264压缩原理

文章目录 1. H264编码参数2. H264编码原理2.1 压缩原理2.2 编码结构解析 3. NALU结构4. H264 annexb模式5. 补充说明5.1 I帧5.2 P帧5.3 B帧 1. H264编码参数 视频质量和⽹络带宽占⽤是相⽭盾的。通常情况下&#xff0c;视频流占⽤的带宽越⾼则视频质量也越⾼&#xff0c;需要的…

zig v0.12.0 发布 — x-cmd 提供 zig 快捷安装方法和 x zig 模块

文章目录 简介功能特点v0.12.0 新特性[重新设计 Autodoc 的工作原理](https://ziglang.org/download/0.12.0/release-notes.html#Redesign-How-Autodoc-Works)语法变更各类标准库变更构建系统变更 常见用法**使用案例**:竞品和相关项目进一步阅读 简介 Zig 是一种通用编程语言…

OpenCV基本图像处理操作(九)——特征匹配

Brute-Force蛮力匹配 Brute-Force蛮力匹配是一种简单直接的模式识别方法&#xff0c;经常用于计算机视觉和数字图像处理领域中的特征匹配。该方法通过逐一比较目标图像中的所有特征点与源图像中的特征点来寻找最佳匹配。这种方法的主要步骤包括&#xff1a; 特征提取&#xff…

VOC2012数据集免费获取

你是否遇到过如下情况&#xff1a; 使用官方网站下载数据集&#xff0c;emmm这效率 我放到网盘中了&#xff0c;有需要的自取 https://pan.quark.cn/s/f8b457086b6c

1.为什么选择Vue框架

参考&#xff1a;百战程序员 为什么选择Vue框架 Vue是什么&#xff1f; 渐进式 JavaScript 框架&#xff0c;易学易用&#xff0c;性能出色&#xff0c;适用场景丰富的 Web 前端框架 为什么要学习Vue Vue是目前前端最火的框架之一Vue是目前企业技术栈中要求的知识点Vue可以…

开源贡献代码之​探索一下CPython

探索一下Cython 本篇文章将会围绕最近给Apache提的一个feature为背景&#xff0c;展开讲讲CPython遇到的问题&#xff0c;以及尝试自己从0写一个库出来&#xff0c;代码也已经放星球了&#xff0c;感兴趣的同学可以去下载学习。 0.背景 最近在给apache arrow提的一个feature因为…

Unity UGUI透明区域点击无效

是这样的&#xff0c;我有一张图&#xff0c;客户给的是1920*1080&#xff0c;但只有中间部分是按钮&#xff0c;是有效像素。为了让空白区域点击无效。需要设置如下 并且加上下面这句 this.GetComponent<Image>().alphaHitTestMinimumThreshold 0.1f;

设计模式学习笔记 - 开源实战三(中):剖析Google Guava中用到的设计模式

概述 上篇文章&#xff0c;我通过 Google Guava 这样一个优秀的开源类库&#xff0c;讲解了如何在业务开发中&#xff0c;发现跟业务无关、可以复用的通用功能模块&#xff0c;并将它们抽离出来&#xff0c;设计成独立的类库、框架或功能组件。 本章再来学习下&#xff0c;Go…

Vue3——组件基础

组件基础 1. 组件定义与使用 1.1 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>组件基础&l…

力扣-LCP 02.分式化简

题解&#xff1a; class Solution:def fraction(self, cont: List[int]) -> List[int]:# 初始化分子和分母为 0 和 1n, m 0, 1# 从最后一个元素开始遍历 cont 列表for a in cont[::-1]:# 更新分子和分母&#xff0c;分别为 m 和 (m * a n)n, m m, (m * a n)# 返回最终的…