深入理解java web分层架构的高内聚低耦合

news2024/9/22 23:30:28

在软件开发中,构建一个高效、可维护且可扩展的应用系统一直是开发者追求的目标。分层架构依赖注入(IOC)是实现这一目标的重要策略。本文将深入探讨三层架构的高内聚特性、低耦合的设计原则,以及如何通过IOC(控制反转)技术来进一步提升应用的灵活性和可维护性。

一、三层架构的含义

三层架构是一种常见的软件设计模式,它将应用程序分为三个主要的逻辑层:表示层(请求层)、业务逻辑层(业务处理层)和数据访问层(数据层)。每个层都有特定的职责,这样设计可以提高系统的可维护性、可扩展性和可复用性。具体介绍如下:
在这里插入图片描述

  1. 请求层(controller):

    请求层是系统与外部交互的接口,负责接收用户的请求或其他系统的调用。

  2. 业务逻辑层:

    这一层主要包含系统的核心业务规则和处理逻辑。它接收来自请求层的请求,进行业务处理和数据加工,然后将结果返回给请求层。

  3. 数据访问层:
    数据访问层主要负责与数据库或其他数据源进行交互,实现数据的存储和读取。它将业务逻辑层的抽象数据操作转换为具体的数据库操作。
    ·


    @RestController
    public class UserController {

        @GetMapping("/getUser")
        public String getUser(@RequestParam("userId") int userId) {
            // 将 userId 传递给服务层进行处理
            return "请求已接收,即将传递给服务层处理 userId: " + userId;
        }
    }

二、三层架构的高内聚

高内聚意味着每个层次内部的功能紧密相关,具有明确的职责和功能边界。
请求层只负责处理客户端发来的网络请求,业务层是负责实现业务逻辑,数据层只负责读取存储数据。

三、三层架构的低耦合

低耦合意味着各个层次之间的依赖关系尽可能地减少,相互之间的影响降到最低
比如服务层的serverA换成了serverB,只用更改服务层的代码,不用修改请求层的代码,这就是低耦合。spring项目通过IOC来实现低耦合性
四、IOC 容器
IOC(Inversion of Control,控制反转)容器是一种用于管理对象创建和依赖关系的工具。
在这里插入图片描述

解耦对象的创建和使用:在传统的软件开发中,对象的创建通常由使用它的代码直
接负责。而在 IOC 容器中,对象的创建和生命周期管理由容器负责,使用对象的
代码只需要从容器中获取所需的对象即可,大大降低了代码之间的耦合度。方便依
赖注入:IOC 容器能够自动将对象之间的依赖关系注入到需要的对象中,使得对象
之间的依赖关系更加清晰和易于管理。

在 Spring 框架里,Spring 容器属于典型的 IOC 容器。举个例子,对于一个订单服
务接口(OrderService),它存在两个实现类(serviceA 与 serviceB)。倘若没有
IOC 容器,那么 controller 类或许就得自行创建相应订单实现类的实例。然而,在
Spring IOC 容器的环境下,仅需在 controller 类中运用依赖注入(比如借助
@Autowired 注解)订单服务接口,并且在对应的实现类上添加 @Service 注解,
Spring 容器便会自动把订单服务实现类的实例注入到 controller 之中。

以下示例代码:

  1. 首先创建订单服务接口 OrderService
public interface OrderService {
    void processOrder();
}
  1. 创建两个实现类 ServiceAServiceB

ServiceA.java

import org.springframework.stereotype.Service;


public class ServiceA implements OrderService {
    @Override
    public void processOrder() {
        System.out.println("ServiceA is processing the order.");
    }
}

ServiceB.java

import org.springframework.stereotype.Service;

@Service
public class ServiceB implements OrderService {
    @Override
    public void processOrder() {
        System.out.println("ServiceB is processing the order.");
    }
}
  1. 创建 Controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {

    @Autowired
    private OrderService orderService;

    @GetMapping("/processOrder")
    public void handleOrder() {
        orderService.processOrder();
    }
}

在上述代码中,@Service 注解用于将 ServiceA 标记为 Spring 管理的服务类。在 OrderController 中,通过 @Autowired 注解实现了对 OrderService 的依赖注入,Spring 容器会根据具体的配置和扫描自动选择合适的实现类注入到 Controller 中。
如果订单服务实现类换成了ServiceB,只用将@Service 注解加到ServiceB上

五、IOC注意事项

  1. 当某个包与启动程序不在同一个包时使用 @ComponentScan
    例子:假设项目的启动类位于 com.example.main 包中,而一些自定义的组件位于 DAO 包中。如果不使用 @ComponentScan 指定包含自定义组件的包,Spring 容器将无法自动扫描和注册这些组件。
    在这里插入图片描述

    代码示例:

@MapperScan({"com.example.springboot","DAO"})
@EnableScheduling
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }

}    
  1. @Autowired 介绍及遇到多个同类型 bean 的解决方案:

    @Autowired 是 Spring 框架中用于自动装配(依赖注入)的注解。它会根据类型自动在 Spring 容器中查找匹配的 bean 并注入到目标对象中。在刚才那个订单服务例子中,有两个订单服务类,如果ServiceA和ServiceB都注入IOC容器内,程序运行时将会报错,因为这个两个都继承了OrderService接口他们的bean类型相同。

    当遇到多个同类型 bean 的情况时,可以使用以下解决方案:

    @Primary:为某个 bean 添加 @Primary 注解,提高其优先级,确保在注入时优先选择该 bean。
    例子:假设有两个 UserRepository 的实现类 UserRepositoryImpl1UserRepositoryImpl2,如果希望 UserRepositoryImpl1 优先被注入,可以在 UserRepositoryImpl1 上添加 @Primary 注解:
    java @Repository @Primary public class UserRepositoryImpl1 implements UserRepository { // 实现方法 }

    @Qualifier("beanName"):在 @Autowired 注解上面添加 @Qualifier 注解,并指定 bean 的名称,可以精确地选择要注入的 bean。
    例子:
    java @Service public class UserService { @Autowired @Qualifier("userRepositoryImpl2") private UserRepository userRepository; // 其他业务方法 }

    @Resource(name = ''):这也是一种指定 bean 名称进行注入的方式,与 @Qualifier 类似。
    例子:
    java @Service public class UserService { @Resource(name = "userRepositoryImpl2") private UserRepository userRepository; // 其他业务方法 }

总之,三层架构结合 IOC 容器和合理的依赖注入技术,能够构建出结构清晰、易于维护和扩展的软件系统。在实际开发中,我们需要根据项目的具体需求和特点,灵活运用这些技术和设计模式,以提高软件的质量和开发效率。

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

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

相关文章

前端宝典之五:React源码解析之深度剖析Diff算法

本文主要针对React源码进行解析,内容有: 1、Diff算法原理、两次遍历 2、Diff瓶颈及限制 3、Diff更新之单节点和多节点原理 一、Diff源码解析 以下是关于 React Diff 算法的详细解析及实例: 1、React Diff 算法的基本概念和重要性 1.1 概念…

非专业人员该学什么程序语言

编程,一度被认为和驾驶一样是一项现代社会的基本技能,非专业人员也该有所掌握,中小学也在教。但实际上,它的普及程度远比驾驶差,掌握这个技能的人很少,在学校学过的知识,因为工作中用不上也都忘…

一文弄懂评分卡是什么

在最开始的信用审批过程中,客户的信用等级主要由专家进行主观评判。随着数据分析工具的发展和数据收集、存储越来越容易,各大机构逐渐使用统计模型将专家的评判标准量化为评分卡模型。从而更有利于客观评价客户风险,和批量高效对客户进行风险分级。随着技术的发展,机器学习…

力扣经典题目~快乐数~零基础也能看懂哦

202. 快乐数https://leetcode.cn/problems/happy-number/ 题目描述: 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&…

MyBatisX逆向工程

目录 逆向工程 准备好数据库、表 安装MyBatisX插件 项目连接数据库 引入依赖pom.xml 生成实体类、映射文件、接口 逆向工程 正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的。 逆向工程:先创…

晶体管电路设计学习(一)放大电路的工作

我们这里学习晶体管电路设计,会从晶体管到场效应管直到复杂的运放器件,主要是进行体系化的深入学习,只是一个学习和记录的过程。 放大电路的作用是将小信号放大为大信号。例如,将0.1V的信号提高为1V 信号----即是放大。 1.首先,用晶体管组成一…

TinyC编译器4—编译器基本流程

1.什么是编译器,为什么要开发编译器 编译器:将一种程序语言翻译为另一种程序语言的计算机程序。一般来说,源程序为高级语言,而目标语言则是汇编语言或者机器码。 一开始的程序员是用机器码写程序,非常容易出错&#…

UE5中制作箭头滑动转场

通过程序化的方式,可以制作一些特殊的转场效果,如箭头划过的转场: 1.制作思路 我们知道向量点积可以拿来做投影,因此可以把UV空间想象成向量坐标,绘制结果就是在某个向量上的投影: 绘制结果似乎是倾斜方…

【ISAC】Federated Edge Learning With Misaligned Over-The-Air Computation

[1]-Tse, David, and Pramod Viswanath. Fundamentals of wireless communication. Cambridge university press, 2005. 文章目录 1-综述2-系统模型 1-综述 misaligned OAC:预编码矩阵(含噪声) 没同步好 2-系统模型 θ ∈ R d \theta \in\m…

云计算实训31——playbook(剧本)基本应用、playbook常见语法、playbook和ansible操作的编排

playbook(剧本): 是ansible⽤于配置,部署,和管理被控节点的剧本。⽤ 于ansible操作的编排。 使⽤的格式为yaml格式 一、YMAL格式 以.yaml或.yml结尾 ⽂件的第⼀⾏以 "---"开始,表明YMAL⽂件的开始(可选的) 以#号开头为注释 列表中的所有成员都开始于…

耐氟化氢PFA蒸馏冷凝装置PFA烧瓶应用于氟化工半导体行业领域

氟化氢,化学式为 HF,是一种无色、有刺激性气味的气体,它在空气中会形成白色的雾。氟化氢具有很强的腐蚀性,能够侵蚀许多金属和非金属材料。这种腐蚀性使得氟化氢在工业上被用于蚀刻玻璃、清洗半导体器件以及加工金属等领域。 氟化…

Ubuntu | 更换 Solc 版本

目录 第一步:安装 pip3第二步:安装 solc-select第三步:查看可安装版本第四步:安装指定版本第五步:使用指定版本 前言:部署智能合约时报错,发现是 Solc 版本太高。 参考博客:Solc 安…

Spring Boot整合Quartz框架

说明:Quartz是一个定时器框架,可以实现定时任务,本文介绍如何在Spring Boot项目中整合Quartz框架,Quartz介绍参看下面这篇文章: 【Quartz】Quartz定时任务框架 创建Demo 首先,创建一个Spring Boot项目&a…

Qt Creator安装配置指南

1.官网下载在线安装包 官网地址: https://www.qt.io/download-dev#eval-form-modal 2.双击在线安装包按引导流程安装qt 3.选择自己要配置的qt环境版本 3.1如果要选中低版本的qt环境我这里安装的是qt5.15.2的(其他低版本也一样的),要勾选上Archive(存…

拓展销售网络:立即领取企元数智小程序合规分销系统!

"拓展销售网络:立即领取企元数智小程序合规分销系统!"企业的销售网络是企业成长和发展的关键,而企元数智小程序合规分销系统能帮助您快速拓展销售网络,实现销售业绩的持续增长。 通过领取企元数智小程序合规分销系统&am…

2024软件测试八股文【答案解析+文档】

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 Part1 1、你的测试职业发展是什么? 测试经验越多,测试能力越高。所以我的职业发展是需要时间积累的,一步步向着高级测试工程师…

Go语言导入gin包

访问https://pkg.go.dev/页面,输入gin 点击README,点击Getting started,点击Getting Gin。 以VSCode通过mod命令导入gin包为例 安装第三方库 go mod init go mod tidy运行成功创建go.mod文件 go get -u github.com/gin-gonic/gin创建Go项目&#xf…

养猫换毛季总结,希喂、小米宠物空气净化器功能测评,真实PK

猫咪作为小家中的一员,陪伴我们度过了非常多时光。而养猫一定会面临换毛季的问题,在换毛季期间,宠物会大量掉毛,不仅破坏家里的整洁,而且还可能被猫咪误吞,导致毛球症。这需要我们铲屎官选找到有效的清理毛…

Spring cloud alibaba(二)RibbonLoadBalance

一、负载均衡 其含义就是将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行;(就是客户端调用服务提供方时的如何调用多个实例的策略) 1、主流负载均衡的方案 集中式负载均衡:在消费者和服务提供方中…

使用excalidraw搭建自己的中文手写画板

使用excalidraw搭建自己的中文手写画板 成品预览地址:https://guizimo.github.io/excalidraw/ 原excalidraw提供了英文的手写体,但中文还是正正方方的,感觉不搭。希望中文也可以有那样一种手写风格。 本文使用的是excalidraw,它…