基于Spring框架的分层解耦详解

  • 博客主页:誓则盟约
  • 系列专栏:Java Web
  • 关注博主,后期持续更新系列文章
  • 如果有错误感谢请大家批评指出,及时修改
  • 感谢大家点赞👍收藏⭐评论✍ 

Java Web 三层架构:

Java Web可以大致被分为三层架构:

  • controller:控制层
  • service:业务逻辑层
  • dao:数据访问层

Controller层:

        controller层也称为控制层,只要功能是接收前端发送的请求,对请求进行处理,并响应数据。

        作为应用程序的入口点之一,Controller 层负责接收来自客户端(如浏览器、移动设备等)的 HTTP 请求。这些请求可以是 GET、POST、PUT、DELETE 等不同类型的请求,例如,在 Web 应用中,当用户在浏览器中输入一个 URL 或者提交一个表单时,请求会被发送到相应的 Controller。

        它会解析请求中的参数,如查询字符串参数(对于 GET 请求)或者表单数据(对于 POST 请求)。例如,在一个登录功能中,Controller 会获取用户输入的用户名和密码参数。

注:Controller 层并不直接实现业务逻辑,而是调用 Service 层(业务逻辑层)的方法来处理业务。

Service层:

        service层也称为业务逻辑层,在 Java 应用架构(特别是遵循 MVC 或类似分层架构的应用)中,Service 层(业务逻辑层)扮演着核心的角色,其中主要是处理具体的业务逻辑。

        Service 层包含了应用的复杂且核心的业务逻辑。例如,在一个银行系统中,转账业务逻辑就会在 Service 层实现。它需要考虑诸如账户余额检查、转账金额的合法性、更新相关账户余额等操作。

        除此之外,Service通常还负责管理事务。在涉及多个数据库操作的业务场景中,如订单处理(包括创建订单、扣减库存、更新用户积分等多个数据库操作),Service 层确保这些操作要么全部成功(提交事务),要么全部失败(回滚事务)。

        在架构中Service 层为 Controller 层提供业务处理方法。Controller 层调用 Service 层的方法来完成具体的业务操作。

Dao层:

        Dao(Data Access Object)层也称为数据访问层,主要负责数据访问操作,包括数据的增删改查。

        Dao 层的主要目的是将数据库操作抽象出来,为上层(通常是 Service 层)提供统一的访问数据库的接口。这样,上层业务逻辑层不需要关心具体的数据库类型(如 MySQL、Oracle 等)以及数据库的底层操作细节(如 SQL 语句的编写、数据库连接的管理等)。例如,在一个企业级应用中,无论是使用关系型数据库还是非关系型数据库,Service 层只需要调用 Dao 层提供的方法(如findUserByIdsaveUser等)就可以实现对数据的操作。

        除此之外,Dao层还负责执行数据的持久化操作,包括将数据保存到数据库(插入操作)、从数据库中查询数据、更新数据库中的数据以及删除数据库中的数据等操作。因此,Dao层也被称为持久层。


分层解耦:

首先要知道内聚和耦合两个概念:

  • 内聚:软件中各个功能模块内部的功能联系。
  • 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。

         在开发过程中,我们要朝着高内聚低耦合的方向实施,最好可以让层与层之间解除耦合,让他们不产生依赖,这样我们程序的灵活性和可扩展性会更佳。

        下面我们以Spring框架为例讲解如何实现解耦操作。在 Spring 框架中,解耦主要通过控制反转(Inversion of Control,IOC)和依赖注入(Dependency Injection,DI)的机制来实现。

控制反转(IOC):

        在没有使用 Spring 等框架进行解耦之前,对象之间的依赖关系通常是由对象自己创建和管理的。例如,在一个业务逻辑类中,如果需要调用数据访问层的方法来获取数据,它可能会直接实例化数据访问层的对象。

   public class BusinessLogicClass {public void doSomeBusinessLogic() {DataAccessClass dataAccess = new DataAccessClass();// 使用 dataAccess 对象进行数据操作}}

        这种方式存在的问题是,业务逻辑类与数据访问类紧密耦合,当数据访问层的实现发生变化时,业务逻辑类也需要进行相应的修改。

        而Spring 框架引入了控制反转的概念,即对象的创建和依赖关系的管理不再由对象自己负责,而是交给一个外部的容器(通常是 Spring 容器)来管理。而在IOC容器中创建、管理的对象,称之为bean

        这样在 Spring 中,对象只需要声明自己所需要的依赖,而不需要关心这些依赖是如何创建和初始化的。例如:

   public class BusinessLogicClass {private DataAccessInterface dataAccess;public BusinessLogicClass(DataAccessInterface dataAccess) {this.dataAccess = dataAccess;}public void doSomeBusinessLogic() {// 使用 dataAccess 对象进行数据操作}}

        这里,BusinessLogicClass不再自己创建DataAccessClass的实例,而是通过构造函数接收一个实现了DataAccessInterface接口的对象。这样,BusinessLogicClass只依赖于接口,而不依赖于具体的实现类,实现了解耦。

依赖注入(DI):

        容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。这些资源一般取自Spring容器中的bean对象。

        Spring 框架通过依赖注入的方式来实现控制反转。依赖注入有多种方式,常见的有构造函数注入、Setter 注入和字段注入。

        构造函数注入:在对象创建时,通过构造函数将依赖对象传递进去。例如上面的例子中,BusinessLogicClass通过构造函数接收DataAccessInterface的实现对象。

        Setter 注入:通过设置方法将依赖对象注入到对象中。

        字段注入:使用注解(如@Autowired)直接在字段上进行依赖注入。例如:

   import org.springframework.beans.factory.annotation.Autowired;public class BusinessLogicClass {@Autowiredprivate DataAccessInterface dataAccess;public void doSomeBusinessLogic() {// 使用 dataAccess 对象进行数据操作}}

解耦的好处:

1.可维护性

        由于对象之间的依赖关系通过接口进行解耦,当一个模块的实现发生变化时,只需要修改对应的实现类,而不会影响到其他模块。例如,如果数据访问层的实现从使用一种数据库切换到另一种数据库,只需要修改数据访问层的实现类和 Spring 配置文件,业务逻辑层不需要做任何修改。

2.可测试性

        解耦后的代码更容易进行单元测试。在测试业务逻辑类时,可以通过注入模拟的依赖对象(如使用模拟框架创建的模拟数据访问对象)来隔离其他模块的影响,只专注于测试业务逻辑本身。

3.可扩展性

        当需要添加新的功能模块时,可以很容易地将新模块集成到系统中,只需要在 Spring 配置文件中定义新模块的 bean,并将其注入到需要的地方即可。例如,添加一个新的业务逻辑模块,只需要在配置文件中定义新的 bean,并将其注入到现有的业务逻辑类中,实现功能的扩展。


欲买桂花同载酒,终不似、少年游。—— 《唐多令·芦叶满汀洲》

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

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

相关文章

怎么在Vue3项目中引入Vant组件库并使用?

文章目录 前言一、项目中使用步骤1.安装:2.样式的导入(2种方法)2.1 main.ts全局导入(平常自己的项目用的这个全局)2.2 按需引入组件样式 (简单介绍一下)1.安装插件2.配置插件 3.组件按需使用:App.vue 总结 …

5QI(5G QoS Identifier)

5QI(5G QoS Identifier,5G 服务质量标识符)是在5G网络中用于定义特定数据流所需服务级别的指标。它用于优先处理流量,并根据流量的类型及其特定需求分配网络资源。5QI值从1到255,每个值对应一组QoS参数,这些…

数据结构和算法基础(一)

文章目录 链表反转链表合并删除链表倒数第 n 个结点找链表的中间结点链表中环的检测排序算法递归 趁空闲时间刷一遍极客时间上王争的《数据结构与算法之美》课程,个人觉得写的很好,每章节由浅入深且从基础到引入设计类问题,如果写过很多代码想…

成都睿明智科技有限公司抖音电商服务靠谱吗?

在这个电商风起云涌的时代,抖音作为短视频直播的超级流量池,正深刻改变着人们的购物习惯。无数商家蜂拥而至,渴望在这片蓝海中找到属于自己的岛屿。而提及抖音电商服务,成都睿明智科技有限公司无疑是一个备受瞩目的名字。那么&…

WebSocket 在 Spring Boot 中的高级应用指南

WebSocket 在 Spring Boot 中的高级应用指南 深入理解WebSocket协议 深入理解STOMP协议 1. 概述 WebSocket 是一种基于 TCP 的全双工通信协议,允许服务器和客户端之间进行持续的双向通信。与传统的 HTTP 请求-响应模型不同,WebSocket 是一个持久的连接…

Linux 进程的基本概念及描述

目录 0.前言 1. 什么是进程 1.1 进程的定义与特性 1.2 进程与线程的区别 2.描述进程 2.1 PCB (进程控制块) 2.2 task_struct 3.查看进程 3.1 查看进程信息 3.1.1 /proc 文件系统 3.1.2 ps 命令 3.1.2 top 和 htop 命令 3.2 获取进程标识符 3.2.1使用命令获取PID 3.2.2 使用C语言…

微信小程序数据操作指南:从绑定到更新

微信小程序数据操作指南:从绑定到更新 在微信小程序开发中,数据操作是核心环节之一。微信小程序提供了一系列简洁而强大的数据操作方法,帮助开发者轻松实现数据的绑定、更新和渲染。本文将详细介绍微信小程序中常用的数据操作方法&#xff0…

加密与安全_HTOP 一次性密码生成算法

文章目录 HOTP 的基础原理HOTP 的工作流程HOTP 的应用场景HOTP 的安全性安全性增强措施Code生成HOTP可配置项校验HOTP可拓展功能计数器(counter)计数器在客户端和服务端的作用计数器的同步机制客户端和服务端中的计数器表现服务端如何处理计数器不同步计…

AIGC学习笔记—minimind详解+训练+推理

前言 这个开源项目是带我的一个导师,推荐我看的,记录一下整个过程,总结一下收获。这个项目的slogan是“大道至简”,确实很简。作者说是这个项目为了帮助初学者快速入门大语言模型(LLM),通过从零…

vue3学习记录-computed

vue3学习记录-computed 1.为什么要用computed2.使用方法2.1 基本实例2.2 可写计算属性 1.为什么要用computed 写个购物车的案例 <script setup> import { ref, reactive,computed } from "vue" const tableData reactive([{ name: 商品1, price: 10, num: 1…

3. 轴指令(omron 机器自动化控制器)——>MC_MoveRelative

机器自动化控制器——第三章 轴指令 5 MC_MoveRelative变量▶输入变量▶输出变量▶输入输出变量 功能说明▶指令详情▶时序图▶重启运动指令▶多重启动运动指令▶异常 MC_MoveRelative 指定自指令当前位置起的移动距离&#xff0c;进行定位。 指令名称FB/FUN图形表现ST表现MC…

初始C语言(五)

前言 本文章就代表C语言介绍以及了解正式完成&#xff0c;后续进行具体分析和详细解析学习。知识根深蒂固才可以应付后来的学习&#xff0c;地基要打好&#xff0c;后续才会轻松。 十四、结构体 结构体是C语言中最最重要的知识点&#xff0c;使得C语言有能力描述复杂的类型。 …

使用fastapi搭建ChatGPT对话后台

使用fastapi搭建ChatGPT对话后台 参考资料&#xff1a;使用fastapi搭建ChatGPT对话后台 效果&#xff1a;在本地构建网页达成类似chatgpt的对话效果&#xff0c;一个字一个字的返回生成结果 ChatGPT初步调用 import os import fastapi import dotenv from httpx import AsyncC…

JVM(HotSpot):字符串常量池(StringTable)

文章目录 一、内存结构图二、案例讲解三、总结 一、内存结构图 JDK1.6 JDK1.8 我们发现&#xff0c;StringTable移入了Heap里面。所以&#xff0c;应该想到&#xff0c;StringTable将受到GC管理。 其实&#xff0c;1.6中&#xff0c;在方法区中的时候&#xff0c;也是受GC管…

从底层理解为什么常量区中的代码不能被修改?

目录 前言&#xff1a;一、了解虚拟地址二、页表映射三、常量区不能被修改的原理四、常量区不可修改的意义 前言&#xff1a; 平时我们在编写代码时都会用到或遇到所谓的常量区或者不可修改的代码&#xff0c;比如说用双引号包起来字符串&#xff08;“Hello World”&#xff…

微服务SpringSession解析部署使用全流程

目录 1、SpringSession简介 2、实现session共享的三种方式 1、修改Tomcat配置文件 2、Nginx负载均衡策略 3、redis统一存储 0、准备工作 1、本地服务添加依赖 2、修改本地服务配置文件 3、添加application.properties文件 4、添加nacos - redis配置 5、修改本地项目…

Egress Gateway 是一个重要的组件,用于管理从服务网格内部到外部服务的流量

在 Istio 服务网格中&#xff0c;Egress Gateway 是一个重要的组件&#xff0c;用于管理从服务网格内部到外部服务的流量。Egress Gateway 充当了一个边界路由器的角色&#xff0c;处理所有从网格内部发出的请求到非网格服务的流量。它可以帮助解决服务网格内外部服务通信的问题…

Linux启动mysql报错

甲方公司意外停电&#xff0c;所有服务器重启后&#xff0c;发现部署在Linux上的mysql数据库启动失败.再加上老员工离职&#xff0c;新接手项目&#xff0c;对Linux系统了解不多&#xff0c;解决起来用时较多&#xff0c;特此记录。 1.启动及报错 1.1 启动语句1 启动语句1&a…

【Rockchip系列】官方函数:drm_buf_alloc

drm_buf_alloc 函数 功能 分配一个DRM&#xff08;Direct Rendering Manager&#xff09;缓冲区。 语法 void* drm_buf_alloc(int width, int height, int bpp, int* fd, int* handle, size_t* size, int flags);参数 width: 缓冲区宽度&#xff08;像素&#xff09;heigh…

全站最详细的Python环境配置步骤

1、官网下载IDE JetBrains下载 2、IDE下载、安装步骤 这里展示的是如何在Windows上下载、安装Pycharm工具&#xff0c;Linux的步骤类似。 2.1、选择开发者工具 选择开发者工具 2.2、选择Pycharm 选择Pycharm 2.3、选择下载 选择下载 2.4、选择社区版 一般而言&#xff…