后端Web之分层解耦(控制反转IOC-依赖注入DI)

devtools/2024/10/18 1:10:54/

目录

1.三层架构

2.IOC-DI引入

3.IOC-DI使用

4.IOC细节

5.DI细节


内聚(Cohesion)和耦合(Coupling)是软件工程中两个重要的概念,它们衡量了软件组件的组织方式和组件之间的相互依赖程度。高内聚性意味着模块内的元素紧密相关,共同协作以完成一个单一、明确定义的任务。低耦合度意味着模块或组件之间的依赖性较低,每个模块可以独立于其他模块进行更改和扩展。

高内聚性通常与低耦合度相辅相成。当模块具有高内聚性时,它通常更加自包含,与其他模块的交互较少,从而降低了耦合度。最好的就是做到解除耦合,对其他模块完全没有依赖。这样修改这一模块的代码,其他模块不用变动。

反之,低内聚性会导致高耦合度。如果模块内的元素执行不相关或松散相关的任务,它们需要依赖其他模块来完成工作,从而增加了耦合度。

1.三层架构

在这个controller中,包含了三个功能,如果要修改其中一个,那么就要同时修改另外两个,这样代码复用性差,并且不利于代码的维护和拓展。

在实际的项目开发中,我们应该尽可能的让每一个接口、类和方法的职责更加单一,也就是每个类只完成一件事。这能够让它们的复杂度降低,并增强可读性。因此,我们采用三层架构去降低耦合度(组件间的依赖程度)。

  • controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据。
  • service:业务逻辑层,处理具体的业务逻辑。
  • dao:数据访问层(Data Access Object) (持久层),负责数据访问操作,包括数据的增、删、改、查。

根据这三层的功能,把上面的代码分别放到各自的层中。

由于我们可能访问的数据不同,比如文件数据、数据库数据或者别人提供的接口中的数据等,为了能够灵活切换访问数据的方式,我们通过面向接口的方式编写Dao层。

2.IOC-DI引入

上面我们只是降低了耦合度,但没有完全解耦。模块之间依然需要通过调用对象来实现自己的功能。因此我们引入控制反转IoC(Inversion of Control)和依赖注入DI(Dependency Injection)。

  • IoC是一种设计原则,它将对象或程序部分的控制权转移给容器或框架,而在面向对象编程中,经常使用依赖注入作为实现IoC的一种模式。
  • 依赖注入指的是对象的依赖关系由容器在运行期决定,通过动态地将依赖关系注入到组件中来实现

简单来说,IOC是指将对象的创建和控制权转移到外部(容器),对象的控制权由程序本身变成了由容器管理,这种思想就叫做控制反转。而依赖注入就是当应用程序(需要对象)运行时,容器提供这个对象资源供于运行,这就叫做依赖注入

这里当EmpController运行时,它需要empservice对象,此时它不去调用EmpServiceB(或者EmpServiceA/C/D等,如果有更多empservice类的话),而是由IOC容器(也叫做Spring容器)提供这个对象。IOC容器中创建、管理的对象就叫做Bean。

它们使得对象的创建和依赖关系交由IOC容器来管理和注入,从而实现了组件之间的解耦和松耦合。

3.IOC-DI使用

使用非常简单,只需要加上注解@Component就完成了控制反转,加上注解@Autowired(自动装配)就完成了依赖注入。

dao层不需要调用其他两个模块,因此只需要IOC(@Component)即可,Service层需要dao层中的对象,因此需要DI(@Autowired),同时它也提供对象给controller,所以也进行IOC,同理,controller只需要DI就行。

如果需要切换业务层的实现,比如新增一个EmpServiceB,我们只需要将EmpServiceA中的IOC(@Component)注释掉,把IOC放在EmpServiceB中,这样容器中就是B的对象了,controller使用的就是B中的业务逻辑。通过改变注解的方法,我们就可以在不改变任何代码的情况下,更改我们业务逻辑。也就实现了解耦

4.IOC细节

通常,我们不直接使用@Componen注解,spring框架提供另外三个注解,以便于标识bean对象是哪个层中的。

bean对象的名字默认是类名的首字母小写,我们可以通过value属性给bean对象一个名字。

Bean组件扫描:bean的声明范围如果在扫描之外,是不会生效的

5.DI细节

如果EmpServiceA和EmpServiceB中的对象都交给容器管理,会直接报错,告诉我们已经有超过一个EmpService类型了。如果我们非要把两个对象都交给容器呢?有以下三个解决方案。

解决方案:

1.加上@Primary注解告诉IOC这个是首要的bean,只注入这个bean。

2.加上@Qualifier注解,指定我们要注入的bean

3.不使用autowired注解了,使用resource注解指定要注入的bean

1和2的注解是由spring提供的,3注解是jdk提供的。


http://www.ppmy.cn/devtools/95140.html

相关文章

OSI 七层网络模型和 TCP/IP 四层网络模型

OSI 七层网络模型 网络的七层架构从下到上主要分为:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层 物理层主要定义物理设备标准,它的主要作用是传输比特流,具体做法是在发送端将 1、0 码转化为电流强弱来进行传输&#xff0…

Linux内核编程(十二)热插拔

本文目录 一、知识点1. 热插拔概念2. 热插拔机制3. Netlink机制 二、内核发送uevent事件到用户空间1. kobject发送uevent事件2. udevadm命令查看★示例代码:★优化:完善kset_uevent_ops(热插拔事件结构体) 三、用户空间使用Netlin…

TypeError: Cannot read properties of undefined (reading ‘scrollIntoView‘)(已解决)

问题复现:眨眼睛使用vitevue3实现跳转dom功能时使用了scrollIntoView方法,在打包上传以后使用该功能报错 小友可能会陷入误区,以为是函数方法有问题,毕竟在开发时是没有问题的, 而实际上呢问题出在获取节点失败了 在这…

使用 Spring Boot 实现职责链模式处理电商订单流程

业务场景 假设我们正在构建一个电商系统,需要处理用户的订单请求。当用户提交订单时,系统需要执行一系列检查和操作,比如验证库存、检查用户信用额度、确认支付方式等。如果所有检查都通过,则订单被创建;否则&#xf…

五个方法帮你克服拖延症,停止内耗!

有人希望我们能出一期干货文,教大家如何克服拖延症?这不?有求必应的我们火速为大家安利几个小诀窍,帮助你停止内耗,告别拖延! 方法一、根据DDL安排时间表 “DDL是第一生产力”这句话简直是拖延患者的口头…

【FreeRTOS】队列实验多设备玩游戏(思路)

目录 0 前言1. 队列实验_多设备玩游戏2 代码分析2.1 讲解2.1.1 球的任务2.1.2 挡球板的任务 2.2 程序改进思路 0 前言 学习视频: 【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS(FreeRTOS教程 基于STM32,以实际项目为导向&#xff09…

AnythingLLM:基于RAG方案构专属私有知识库(开源|高效|可定制)

一、前言 继OpenAI和Google的产品发布会之后,大模型的能力进化速度之快令人惊叹,然而,对于很多个人和企业而言,为了数据安全不得不考虑私有化部署方案,从GPT-4发布以来,国内外的大模型就拉开了很明显的差距…