Spring IOC基于XML和注解管理Bean

IoC 是 Inversion of Control 的简写,译为“ 控制反转 ”,它不是一门技术,而是一种设计思想,是一个重要的面向对象编程法则,能够指导我们如何设计出 松耦合、更优良的程序。

Spring 通过 IoC 容器来管理所有 Java 对象的实例化和初始化,控制对象与对象之间的依赖关系。将由 IoC 容器管理的 Java 对象称为 Spring Bean,它与使用关键字 new 创建的 Java 对象没有任何区别。

IoC 容器是 Spring 框架中最重要的核心组件之一,它贯穿了 Spring 从诞生到成长的整个过程。

IOC容器

1.控制反转,依赖注入

控制反转(Inversion of Control,简称IoC)是一种软件设计原则,它将传统的程序控制流程反转过来,即由被调用者控制调用者的执行过程。这样做的好处在于降低了代码之间的耦合性,使得代码更加灵活、可维护和可扩展。

一个典型的控制反转例子是使用依赖注入(Dependency Injection,简称DI)。依赖注入是控制反转的一种实现方式,它通过将依赖关系从代码内部移动到外部来实现解耦。

假设我们有一个简单的应用程序,其中包含一个服务类 MessageService 负责发送消息,并且这个服务类依赖于一个用于实际发送消息的 MessageSender 接口。在传统的实现中,MessageService 通常会直接创建一个特定的 MessageSender 实例,但在使用控制反转的思想下,我们会将 MessageSender 的创建和注入从 MessageService 中分离出来。

传统实现(无控制反转):

public class MessageService {private MessageSender messageSender;public MessageService() {// 在构造函数中直接实例化特定的 MessageSender 实例this.messageSender = new EmailMessageSender(); // 假设使用 EmailMessageSender 发送消息}public void sendMessage(String message) {messageSender.send(message);}
}

使用控制反转(依赖注入):

public class MessageService {private MessageSender messageSender;public MessageService(MessageSender messageSender) {// 通过构造函数接收一个 MessageSender 实例,由外部注入this.messageSender = messageSender;}public void sendMessage(String message) {messageSender.send(message);}
}

现在,使用控制反转,我们将 MessageSender 的实例化过程交由调用者来完成。这样做的好处是,在应用程序的其他地方,我们可以根据需要轻松地更换不同的 MessageSender 实现(例如,使用短信发送消息而不是电子邮件),而无需修改 MessageService 的代码。同时,这也使得单元测试变得更容易,因为我们可以轻松地注入一个模拟的 MessageSender 实例来进行测试。

举例:
如果你希望在使用短信发送消息而不是电子邮件时进行更改,只需更改 MessageService 类的构造函数中注入的 MessageSender 实例即可。这就是控制反转的好处,它使得我们可以在应用程序的其他地方配置不同的实现,并且只需更改依赖注入的部分,而不需要修改 MessageService 的实现代码。

让我们看一下如何在 MessageService 中使用短信发送消息的例子:

  • 创建一个用于发送短信的实现类 SmsMessageSender:
public class SmsMessageSender implements MessageSender {public void send(String message) {// 实现发送短信的逻辑System.out.println("Sending SMS: " + message);}
}
  • 现在,在使用 MessageService 的地方,通过构造函数将 SmsMessageSender 注入:
public class MyApp {public static void main(String[] args) {// 使用短信发送消息MessageSender smsSender = new SmsMessageSender();MessageService messageService = new MessageService(smsSender);// 发送消息messageService.sendMessage("Hello, this is a text message!");}
}

通过这样的更改,MessageService 现在使用 SmsMessageSender 来发送消息而不是之前的 EmailMessageSender,而且这个更改只发生在应用程序的一个地方,使得代码更易于维护和扩展。同时,你可以根据需要在其他地方继续使用 EmailMessageSender,并且无需对 MessageService 的实现进行任何修改。

set注入和依赖注入

在依赖注入(Dependency Injection,DI)的实践中,有两种常见的注入方式:构造函数注入(Constructor Injection)和属性/方法注入(Setter Injection)。

构造函数注入(Constructor Injection):
构造函数注入是将依赖通过类的构造函数传递进来的方式。在这种注入方式中,类的依赖关系在创建对象时就被明确地传递给对象,保证了对象在被实例化后就具备了所需的依赖。这种注入方式通常被认为是推荐的注入方式,因为它在对象创建过程中就明确了依赖关系,使得对象在创建后处于一种可用的状态。
示例:构造函数注入的Java代码

public class MessageService {private MessageSender messageSender;public MessageService(MessageSender messageSender) {this.messageSender = messageSender;}// 业务逻辑方法使用依赖发送消息public void sendMessage(String message) {messageSender.send(message);}
}

属性/方法注入(Setter Injection):
属性/方法注入是通过setter方法或者普通方法将依赖传递给对象的方式。在这种注入方式中,对象首先由默认构造函数创建,然后通过setter方法或者普通方法设置其依赖。由于依赖在创建对象后才被注入,因此在对象实例化时,它可能处于不完整或不可用的状态,这是它与构造函数注入的主要区别。
示例:属性/方法注入的Java代码

public class MessageService {private MessageSender messageSender;// 通过setter方法注入依赖public void setMessageSender(MessageSender messageSender) {this.messageSender = messageSender;}// 业务逻辑方法使用依赖发送消息public void sendMessage(String message) {messageSender.send(message);}
}

需要注意的是,属性/方法注入可能导致对象处于不完整或不可用的状态,因此需要在使用对象之前确保其依赖已经被正确注入。另一方面,构造函数注入在对象创建时就明确了依赖关系,因此更容易维护和确保对象的完整性。

通常情况下,如果可能,推荐使用构造函数注入,因为它更符合依赖注入的原则,能够在对象创建时就将依赖传递进来,减少了对象的不稳定性。而属性/方法注入则适用于一些特殊情况,例如使用框架进行依赖注入时可能更为便利,或者在某些场景下灵活性要求较高时使用。

2.IoC容器在Spring的实现

Spring 的 IoC 容器就是 IoC思想的一个落地的产品实现。IoC容器中管理的组件也叫做 bean。在创建 bean 之前,首先需要创建IoC 容器。Spring 提供了IoC 容器的两种实现方式:

①BeanFactory

这是 IoC 容器的基本实现,是 Spring 内部使用的接口。面向 Spring 本身,不提供给开发人员使用。

②ApplicationContext

BeanFactory 的子接口,提供了更多高级特性。面向 Spring 的使用者,几乎所有场合都使用 ApplicationContext 而不是底层的 BeanFactory。

③ApplicationContext的主要实现类
在这里插入图片描述

类型名简介
ClassPathXmlApplicationContext通过读取类路径下的 XML 格式的配置文件创建 IOC 容器对象
FileSystemXmlApplicationContext通过文件系统路径读取 XML 格式的配置文件创建 IOC 容器对象
ConfigurableApplicationContextApplicationContext 的子接口,包含一些扩展方法 refresh() 和 close() ,让 ApplicationContext 具有启动、关闭和刷新上下文的能力。
WebApplicationContext专门为 Web 应用准备,基于 Web 环境创建 IOC 容器对象,并将对象引入存入 ServletContext 域中。

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

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

相关文章

如何从 Windows 11/10/8.1/8/7 恢复已删除的视频

意外删除了视频或格式化了 SD 卡/硬盘?没有备份已删除的视频?别担心,我们有解决方案来恢复 Windows 11、10 中已删除的视频并处理这种糟糕的情况。 但在了解如何恢复已删除的视频和视频恢复应用程序之前,请知道 Windows 会为您提…

ARMv8寄存器详解

文章目录 一、ARMv8寄存器介绍二、通用寄存器三、 PSTAE寄存器四、特殊寄存器五、系统寄存器 一、ARMv8寄存器介绍 本文我来给大家介绍一下ARMv8的寄存器部分,ARMv8中有34个寄存器,包括31个通用寄存器、一个栈指针寄存器SP(X31),一个程序计数器寄存器PC…

Apache Drill 2万字面试题及参考答案

目录 什么是Apache Drill? Apache Drill的主要特点是什么? Apache Drill如何实现对复杂数据的查询? 描述Apache Drill的数据存储模型。 为什么Apache Drill被称为自服务的SQL查询引擎? Apache Drill支持哪些类型的数据源? 解释Apache Drill中的“schema discovery”…

Transformer前置知识:Seq2Seq模型

Seq2Seq model Seq2Seq(Sequence to Sequence)模型是一类用于将一个序列转换为另一个序列的深度学习模型,广泛应用于自然语言处理(NLP)任务,如机器翻译、文本摘要、对话生成等。Seq2Seq模型由编码器&#…

《框架封装 · 统一异常处理和返回值包装》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…

贪心算法-以高校科研管理系统为例

1.贪心算法介绍 1.算法思路 贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一 步都要确保能获得局部最优解。每一步只考虑一 个数据,其选取应该满足局部优化的条件。若下 一个数据和部分最优解连在一起…

JavaEE初阶-网络原理1

文章目录 前言一、UDP报头二、UDP校验和2.1 CRC2.2 md5 前言 学习一个网络协议,最主要就是学习的报文格式,对于UDP来说,应用层数据到达UDP之后,会给应用层数据报前面加上UDP报头。 UDP数据报UDP包头载荷 一、UDP报头 如上图UDP的…

Kubernetes(K8s) kubectl 常用命令

文章目录 一、常用命令1.1 kubectl describe 命令 二、kubectl 命令中的简写三、Helm3.1 常用命令:3.2 遇到的问题3.2.1 cannot re-use a name that is still in use 四、Containerd 一、常用命令 检查 k8s 各节点状态,确保k8s集群各节点状态正常&#x…

概率基础——矩阵正态分布matrix normal distribution

矩阵正态分布-matrix normal distribution 定义性质应用 最近碰到了这个概念,记录一下 矩阵正态分布是一种推广的正态分布,它应用于矩阵形式的数据。矩阵正态分布在多维数据分析、贝叶斯统计和机器学习中有广泛的应用。其定义和性质如下: 定…

Emacs之解决:java-mode占用C-c C-c问题(一百四十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

【django项目使用easycython编译】Cannot convert Unicode string to ‘str‘ implicitly.

django项目编译遇到的问题 报错条件 需要编译的python源码里面的函数写了type hint,尤其是return的type hint, 当type hint是str时,但是变量确实f-string格式化后得到的,编译时会报错 报错原因 easycython会检查变量类型&…

软件开发中的原型开发与需求文档开发:哪个更优?

1. 引言 在软件开发过程中,选择合适的开发方法对于项目的成功至关重要。基于原型开发和基于需求文档开发是两种常见的开发方法,各自有其优点和缺点。在项目复杂性、客户需求和资源限制等因素的影响下,开发团队需要慎重选择适合的开发方法。 …

C++语言相关的常见面试题目(二)

1.vector底层实现原理 以下是 std::vector 的一般底层实现原理: 内存分配:当创建一个 std::vector 对象时,会分配一块初始大小的连续内存空间来存储元素。这个大小通常会随着 push_back() 操作而动态增加。 容量和大小:std::vec…

element-plus 的form表单组件之el-radio(单选按钮组件)

单选按钮组件适用于同一组类型的选项只能互斥选择的场景,就是支持单选。单选组件包含以下3个组件 组件名作用el-radio-group单选组组件,子元素可以是el-radio或el-radio-button,v-mode绑定单选组的响应式属性el-radio单选组件,la…

阶段三:项目开发---搭建项目前后端系统基础架构:任务9:导入空管基础数据

任务描述 本阶段任务是导入项目的基础数据,包括空管基础数据和离线的实时飞行数据(已经脱敏)。 任务指导 本阶段任务需要导入两种数据: 1、在MySQL中导入空管基础数据 kongguan.sql空管基础数据表说明: 1告警信息…

OpenCV直方图计算函数calcHist的使用

操作系统:ubuntu22.04OpenCV版本:OpenCV4.9IDE:Visual Studio Code编程语言:C11 功能描述 图像的直方图是一种统计表示方法,用于展示图像中不同像素强度(通常是灰度值或色彩强度)出现的频率分布。具体来说…

对MsgPack与JSON进行序列化的效率比较

序列化是将对象转换为字节流的过程,以便在内存或磁盘上存储。常见的序列化方法包括MsgPack和JSON。以下将详细探讨MsgPack和JSON在序列化效率方面的差异。 1. MsgPack的效率: 优点: 高压缩率: MsgPack采用高效的二进制编码格式&…

Embedding理解

一、概念 Embedding 可以理解为一种将概念、物体或信息转换为数字序列的数值表示方法。它是沟通两个不同世界或领域的桥梁,能够把各种类型的数据(如文本、图像、视频等)映射到一个向量空间中。 在这个向量空间里,相似的项目(例如语义上相近的单词、相似的图像或相关的视…

cs231n作业1——SVM

参考文章:cs231n assignment1——SVM SVM 训练阶段,我们的目的是为了得到合适的 𝑊 和 𝑏 ,为实现这一目的,我们需要引进损失函数,然后再通过梯度下降来训练模型。 def svm_loss_naive(W, …

【Qt】Qt概述

目录 一. 什么是Qt 二. Qt的优势 三. Qt的应用场景 四. Qt行业发展方向 一. 什么是Qt Qt是一个跨平台的C图形用户界面应用程序框架,为应用程序开发者提供了建立艺术级图形界面所需的所有功能。 Qt是完全面向对象的,很容易扩展,同时Qt为开发…