当前位置: 首页 > news >正文

Java后端开发——分层解耦详解

文章目录

    • 一、三层架构
      • 1.1 概述
      • 1.2 具体实现方法
    • 二、分层解耦
      • 2.1 以往问题
      • 2.2 概念解释
      • 2.3 解耦思路
    • 三、Spring核心:IOC & DI
      • 3.1 快速入门
      • 3.2 IOC(控制反转)详解
      • 3.3 DI(依赖注入)详解 注入方式

标签:JavaWeb、三层架构、分层解耦、Spring、IOC、DI

一、三层架构

1.1 概述

为什么要采用三层架构?

  • 遵循单一职责原则,便于代码复用和后期维护。
  • 在程序设计和开发时,让每一个接口、类、方法的职责尽可能单一。
  • 代码拆分为以下三层:
    • controller :控制层,接收前端请求,处理请求并响应数据。
    • service :业务逻辑层,处理具体业务逻辑。
    • dao :数据访问层(Data Access Object,持久层),负责数据的增删改查。

在这里插入图片描述

1.2 具体实现方法

在 service 和 dao 层中,通常会先定义接口(命名规范为对象名+Service/Dao),再用实现类(命名规范为接口名+Impl)去实现接口,最后通过调用方法进行业务设计。


二、分层解耦

2.1 以往问题

  • 直接用 new 创建对象,业务变更时需要频繁更换对象,导致各层级耦合度高,影响维护与扩展。

在这里插入图片描述

2.2 概念解释

  • 耦合 :衡量软件各层/模块之间的依赖关联程度。
  • 内聚 :模块内部各功能之间的联系。
  • 高内聚低耦合 :高内聚指模块内部联系紧密,低耦合指模块之间依赖越低越好。
    高内聚、低耦合的目标是提升程序模块的可重用性和移植性,因此需要解耦。

2.3 解耦思路

  • 将项目中的类交由 IOC 容器管理(控制反转,IOC)。
  • 应用运行时需要对象时,直接依赖容器提供(依赖注入,DI)。

三、Spring核心:IOC & DI

3.1 快速入门

  • Dao 和 Service 层实现类加 @Component 注解,交由 IOC 容器管理。
  • Controller 和 Service 层通过 @Autowired 注入依赖对象。

3.2 IOC(控制反转)详解

Spring 框架为更好地标识 bean 所属层次,提供了 @Component 及其衍生注解:

注解说明位置
@Component声明bean的基础注解不属于以下三类时,用此注解
@Controller@Component的衍生注解标注在控制层类上
@Service@Component的衍生注解标注在业务层类上
@Repository@Component的衍生注解标注在数据访问层类上(由于与mybatis整合,用的少)

示例:

Service 层

@Service  
public class UserServiceImpl implements UserService {  @Autowired  private UserDao userDao;  @Override  public List<User> findAll(){  List<String> lines = userDao.findAll();  List<User> users = lines.stream().map(line -> {  String[] s1 = line.split(",");  String ID = s1[0];  String username = s1[1];  Integer password = Integer.parseInt(s1[2]);  String name= s1[3];  Integer age = Integer.parseInt(s1[4]);  LocalDateTime updateTime = LocalDateTime.parse(s1[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));  return new User(ID,username,password,name,age,updateTime);  }).collect(Collectors.toList());  return users;  }  
}

Dao 层

@Repository  
public class UserDaoImpl implements UserDao {  @Override  public List<String> findAll() {  InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("user.txt");  ArrayList<String> lines = IoUtil.readLines(resourceAsStream, StandardCharsets.UTF_8, new ArrayList<>());  return lines;  }  
}

注意:

  • 声明 bean 时可通过 value 属性指定 bean 名,未指定则为类名首字母小写。
  • 控制器 bean 只能用 @Controller 注解。
  • @ComponentScan 注解(包含在 @SpringBootApplication 中)会自动扫描启动类所在包及其子包。

3.3 DI(依赖注入)详解 注入方式

  • 属性注入

    @Autowired 
    private UserService userService;
    
    • 优点:简洁高效
    • 缺点:隐藏依赖关系,可能破坏封装性
  • 构造函数注入

    @Autowired 
    public UserController(UserService userService) { this.userService = userService; 
    }
    
    • 优点:依赖关系清晰,安全性高(可用final)
    • 缺点:代码稍繁琐,参数多时臃肿
    • 注意:只有一个构造函数时, @Autowired 可省略
  • Setter方法注入

    @Autowired 
    public void setUserService(UserService userService) {
    this.userService = userService; 
    }
    
    • 优点:封装性好,依赖关系清晰
    • 缺点:需额外编写Set方法,代码量大
      实际开发中,属性注入和构造函数注入最常用,官方推荐构造函数注入。
      多个 Bean 对象注入的解决方案
  • @Primary :指定默认实现

    @Primary
    @Service
    public class UserServiceImpl implements UserService {}
    
  • @Qualifier :指定注入的 bean 名称,需配合 @Autowired

    @Qualifier("userServiceImpl")
    @Autowired
    private UserService userService;
    
  • @Resource :按 bean 名称注入

    @Resource(name = "userServiceImpl")
    private UserService userService;
    

相关文章:

Java后端开发——分层解耦详解

文章目录 一、三层架构1.1 概述1.2 具体实现方法 二、分层解耦2.1 以往问题2.2 概念解释2.3 解耦思路 三、Spring核心&#xff1a;IOC & DI3.1 快速入门3.2 IOC&#xff08;控制反转&#xff09;详解3.3 DI&#xff08;依赖注入&#xff09;详解 注入方式 标签&#xff1a;…...

论文如何降低AIGC?(完整指南版)

最近一段时间&#xff0c;关于论文AIGC率太高怎么办的问题&#xff0c;真的是知乎、小红书、B站到处都是&#xff01; 尤其是今年知网一升级&#xff0c;连纯手写的内容都能给你标疑似AIGC&#xff0c;简直离谱啊兄弟姐妹们&#x1f62d;&#xff01; 那论文到底怎么降低AIGC…...

【LCMM】纵向轨迹模型,组轨迹模型

latent_class_mixed_models 基础知识 增长混合模型&#xff08;GMM&#xff09;和潜在类别增长模型&#xff08;LCGA&#xff09;的核心区别确实主要在于是否允许类别内存在随机效应&#xff0c;但两者的差异还涉及模型灵活性、假设和应用场景等方面。以下是详细对比&#xf…...

Flask + ajax上传文件(三)--图片上传与OCR识别

本教程将详细介绍如何使用Flask框架构建一个图片上传与文字识别(OCR)的Web应用。我们将使用EasyOCR作为OCR引擎,实现一个支持中文和英文识别的完整应用。 环境准备 首先,确保你已经安装了Python 3.7+环境,然后安装必要的依赖库: pip install flask easyocr pillow werkz…...

观察者模式 (Observer Pattern)

观察者模式(Observer Pattern)是一种行为型设计模式。它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象的状态发生变化时,会自动通知所有观察者对象,使它们能够自动更新自己的状态。 一、基础 1. 意图 核心目的:定义对象间的一种一对…...

【Leetcode 每日一题】2444. 统计定界子数组的数目

问题背景 给你一个整数数组 n u m s nums nums 和两个整数 m i n K minK minK 以及 m a x K maxK maxK。 n u m s nums nums的定界子数组是满足下述条件的一个子数组&#xff1a; 子数组中的 最小值 等于 m i n K minK minK。子数组中的 最大值 等于 m a x K maxK maxK…...

LeetCode热题100——70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1 阶 1 阶2 阶 示例 2&#xff1a; …...

黑马Java基础笔记-4

方法 什么是方法 方法是程序中最小的执行单元。 形参和实参 调用 直接调用 getSum(10,20,30);赋值调用 int sum getSum(10,20,30);输出调用 System.out.println(getSum(10,20,30));方法的重载 在同一个类中&#xff0c;定义了多个同名的方法&#xff0c;这些同名的方法…...

【Python】Python中的浅拷贝和深拷贝

在Python中&#xff0c;浅拷贝&#xff08;shallow copy&#xff09;和深拷贝&#xff08;deep copy&#xff09;是两种不同的对象复制方式&#xff0c;它们在复制对象时的行为有所不同&#xff1a; 浅拷贝&#xff08;Shallow Copy&#xff09; 浅拷贝是创建一个新对象&…...

使用 LangGraph 和 Elasticsearch 构建强大的 RAG 工作流

作者&#xff1a;来自 Elastic Neha Saini 在这篇博客中&#xff0c;我们将向你展示如何配置和自定义 LangGraph Retrieval Agent 模板与 Elasticsearch&#xff0c;以构建一个强大的 RAG 工作流&#xff0c;实现高效的数据检索和由 AI 驱动的响应。 Elasticsearch 原生集成了…...

云原生--核心组件-容器篇-2-认识下Docker(三大核心之镜像,容器,仓库)

1、Docker基本概念 &#xff08;1&#xff09;、定义 Docker是一种开源的应用容器引擎&#xff0c;是基于操作系统级虚拟化技术。允许开发者将应用程序及其依赖项打包到一个可移植的容器中&#xff0c;然后发布到任何支持Docker的环境中运行。Docker容器是轻量级、独立且可执…...

智慧园区IOT项目与AI时代下的机遇 - Java架构师面试实战

在互联网大厂的Java求职者面试中&#xff0c;面试官通常会针对实际业务场景提出一系列问题。以下是关于智慧园区IOT项目及AI时代下的机遇的面试模拟对话。 第一轮提问 面试官&#xff1a;马架构&#xff0c;请简要介绍下智慧园区IOT项目的整体架构设计。 马架构&#xff1a;…...

Unity中文件上传以及下载,获取下载文件大小的解决方案

首先现在Unity插件那么的广泛的情况下,很多东西都不需要自己实现,直接使用第三方插件就可以了,但为什么这里需要自己写,接下来说明原因。 在Unity商城中有很多关于关于网络接口调用的插件,其中有一款叫BestHTTP这款使用比较广泛的插件,不知道朋友们是不是都知道,是不是…...

Word/WPS 删除最后一页空白页,且保持前面布局样式不变

如题&#xff0c;试了多种方法&#xff0c;都不行。主要是可能的原因太多了&#xff0c;没有通解&#xff0c;这只是适用于我的情况。 解决方案&#xff1a; 首先光标放在倒数第二页&#xff08;即想保留的最后一页&#xff09;&#xff0c;点击页面右下角这个小箭头&#xff…...

MySQL长事务的隐患:深入剖析与解决方案

MySQL长事务的隐患&#xff1a;深入剖析与解决方案 一、什么是长事务&#xff1f; 在数据库系统中&#xff0c;长事务(Long Transaction)通常指执行时间超过预期或系统设定阈值的事务。对于MySQL而言&#xff0c;虽然没有严格的时间定义&#xff0c;但一般认为执行时间超过数…...

【Tauri】桌面程序exe开发 - Tauri+Vue开发Windows应用 - 比Electron更轻量!8MB!

效果图 Tauri的二进制文件体积显著小于Electron&#xff0c;安装包通常缩小80%以上。应用启动更快&#xff0c;内存占用更低&#xff0c;尤其在老旧设备上体验更流畅。 写在前面 Tauri官网 https://tauri.app/zh-cn/支持语言&#xff1a;js、ts、rust、.net编译出来的exe文件&…...

2025春季NC:3.1TheTrapeziumRule

3.1TheTrapeziumRule 📐 The Idea Instead of finding the exact area under a curve y = f ( x ) y = f(x) y=...

【摩尔定律】

一、摩尔定律的核心定义​​ ​​原始表述&#xff08;1965年&#xff09;​​ “集成电路上可容纳的晶体管数量&#xff0c;每隔约 ​​18-24个月​​ 便会增加一倍&#xff0c;同时性能提升一倍&#xff0c;而成本下降一半。” ​​简化理解​​ 芯片的 ​​晶体管密度​​ 和…...

Maven 依赖冲突调解与版本控制

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…...

《Python Web部署应知应会》Flask网站隐藏或改变浏览器URL:从Nginx反向代理到URL重写技术

Flask网站隐藏或改变浏览器显示URL地址的实现方案&#xff1a;从Nginx反向代理到URL重写技术 引言 在Web应用开发中&#xff0c;URL路径的安全性往往被忽视&#xff0c;这可能导致网站结构和后端逻辑被攻击者轻易推断。对于Flask框架开发的网站&#xff0c;如何隐藏或改变浏览…...

6.2 内容生成与营销:个性化内容创作与营销策略优化

随着消费者对个性化体验的需求日益增长&#xff0c;传统的内容创作与营销方式已难以满足市场竞争的需要。基于大语言模型&#xff08;LLM&#xff09;与智能代理&#xff08;Agent&#xff09;的技术为企业提供了全新的解决方案&#xff0c;能够实现高效、精准、规模化的内容生…...

平面连杆机构(上)

1、平面四杆机构的类型与演化 1&#xff09;平面四杆机构的类型 a、铰链四杆机构&#xff1a;曲柄摇杆机构、双曲柄机构、双摇杆机构 b、其他四杆机构&#xff1a;曲柄滑块机构、导杆机构、滑块机构、双滑块机构、偏心轮四杆机构...... 2&#xff09;平面四杆机构的演化 a、…...

【数据结构刷题】顺序表与ArrayList

【数据结构刷题】顺序表与ArrayList 1. 杨辉三角2. 合并两个有序数组 1. 杨辉三角 LC链接&#xff1a;杨辉三角 //杨辉三角import java.util.ArrayList; import java.util.List;public class Demo1 {public List<List<Integer>> generate(int numRows) {List<…...

顶点着色器和片元着色器染色+表面体着色器染色

顶点/片元着色器染色 创建材质球及Shader同名文件VFColor //Update NOTE&#xff1a;replaced mul(UNITY_MATRIX_MVP,*) with UnityObjectToClipPos(*) Shader "CreateTest/VFColor" {Properties{_Color("颜色",Color)(1,1,1,1)}SubShader{Pass{//顶点片…...

240426 leetcode exercises

240426 leetcode exercises jarringslee 文章目录 240426 leetcode exercises[1669. 合并两个链表](https://leetcode.cn/problems/merge-in-between-linked-lists/?envTypeproblem-list-v2&envIdlinked-list)&#x1f501;基础版 保存断点&#xff0c;先拼再补&#x1f…...

代码随想录算法训练营Day35

卡码网46.携带研究材料 力扣494.目标和【meidum】 力扣416.分割等和子集【medium】 一、卡码网46.携带研究材料 题目链接&#xff1a;卡码网46.携带研究材料 视频链接&#xff1a;代码随想录 题解链接&#xff1a;代码随想录 1、思路 dp[i][j] 表示从下标为 [0-i] 的物品里任意…...

C++17 折叠表达式

C17 引入的折叠表达式&#xff08;Fold Expressions&#xff09; 是处理可变参数模板&#xff08;Variadic Templates&#xff09;的革命性特性。它通过简洁的语法&#xff0c;使得对参数包&#xff08;Parameter Pack&#xff09;的操作更加直观和高效&#xff0c;避免了传统的…...

Ubuntu编译opencv源码

准备 Ubuntu版本&#xff1a;22.04opencv版本&#xff1a;4.9.0没下载Ubuntu镜像的可以在清华镜像下载 本文以4.9.0版本演示&#xff0c;可根据自身情况选择 安装JDK和依赖项 本次编译主要为了获取java在linux环境下的动态库&#xff0c;所以需要在虚拟机上下载jdk # 安装…...

一种滑窗像素自差值的深度学习损失函数

公司项目&#xff0c;已申请专利。 深度学习作为新兴技术在图像领域蓬勃发展&#xff0c;因其自主学习图像数据特征避免了人工设计算法的繁琐&#xff0c;精准的检测性能、高效的检测效率以及对各种不同类型的图像任务都有比较好的泛化性能&#xff0c;使得深度学习技术在图像领…...

【Typecho】给Joe主题后台添加custom自定义功能!

大家好&#xff0c;今天来添加一下自定义功能&#xff01; &#x1f602; 温馨提示&#xff1a;站长已经通过本地环境测试custom自定义功能&#xff0c;功能正常可以使用&#xff0c;按照我的操作来一定成功&#xff01; 大纲 创建custom.php粘贴代码到custom.php文件引入cus…...

一些常见的资源池管理、分布式管理和负载均衡的监控工具

资源池管理监控工具 Prometheus 是一款开源的系统监控和警报工具。它可以通过收集各种指标数据,如CPU使用率、内存使用量、磁盘I/O等,来监控资源池中的服务器、容器等资源。Prometheus具有强大的查询语言和可视化功能,能够帮助管理员快速了解资源的使用情况,并及时发现潜在…...

WPF程序使用Sugar操作数据库

WPF 程序使用 Sugar ORM 操作数据库 一、引言 在 WPF(Windows Presentation Foundation)应用程序中,数据库操作是不可或缺的一部分。Sugar ORM(对象关系映射)是一种轻量级的 ORM 框架,它简化了数据库操作,使得开发者能够以面向对象的方式与数据库进行交互。本文将详细…...

【Castle-X机器人】四、智能机械臂安装与调试

持续更新。。。。。。。。。。。。。。。 【Castle-X机器人】智能机械臂安装与调试 四、智能机械臂安装与调试2.1 安装2.2 调试2.2.1 2D摄像头测试 四、智能机械臂安装与调试 2.1 安装 使用相应工具将机械臂固定在Castle-X机器人底盘 2.2 调试 2.2.1 2D摄像头测试 内容地址 链…...

goweb-signup注册功能实现

注册功能 route.go package routerimport ("bluebell/controller""github.com/gin-gonic/gin" )func SetupRouter(mode string) *gin.Engine {r : gin.Default()r.POST("/signup", controller.SignupHandler)return r }UserController.go pac…...

Linux: 如何在VMware上安装Ubuntu操作系统

在VMware上安装Ubuntu操作系统是一个相对简单的过程&#xff0c;以下是详细的步骤&#xff1a; 一、准备工作 安装VMware软件 确保你已经在电脑上安装了VMware Workstation&#xff08;适用于Windows&#xff09;或VMware Fusion&#xff08;适用于Mac&#xff09;。如果没有安…...

详解 Network.framework:iOS 网络开发的新基石

详解 Network.framework&#xff1a;iOS 网络开发的新基石 引言 自 iOS 12 和 macOS 10.14 起&#xff0c;Apple 推出了一个新的网络开发框架 —— Network.framework。它被定位为下一代网络连接的基础设施&#xff0c;让开发者可以以更安全、更高效的方式&#xff0c;管理 T…...

Java—— 五道算法水题

第一题 需求&#xff1a; 包装类&#xff1a;键盘录入一些1~100之间的整数&#xff0c;并添加到集合中。直到集合中所有数据和超过200为止 代码实现&#xff1a; import java.util.ArrayList; import java.util.Scanner;public class Test1 {public static void main(String[]…...

将服务器接到路由器上访问

应用场景: 实验室网卡更换了,新网卡没有报备到校园网,暂时无法通过外部链接连到服务器. 除了跳板机之外,可以使用以下方法将服务器接入到路由器访问. 将服务器接到交换机上&#xff0c;将交换机接到路由器上本地电脑 连接路由器wifi登录http://192.168.0.1/&#xff0c;访问路…...

MyBatis缓存配置的完整示例,包含一级缓存、二级缓存、自定义缓存策略等核心场景,并附详细注释和总结表格

以下是MyBatis缓存配置的完整示例&#xff0c;包含一级缓存、二级缓存、自定义缓存策略等核心场景&#xff0c;并附详细注释和总结表格&#xff1a; 1. 一级缓存&#xff08;默认开启&#xff09; // 使用同一SqlSession执行两次查询&#xff0c;自动命中一级缓存 try (SqlSe…...

我爱学算法之—— 二分查找(上)

了解二分算法 二分查找&#xff0c;想必多多少少有一点了解了&#xff0c;我们了解的二分查找算法&#xff1a; 当一个数组有序的时候&#xff0c;我们可以使用二分算法来查找一个值&#xff1b; 直接比较mid((left right)/2)和我们要查找的值target&#xff1b;如果nums[mid]…...

Tauri快速入门1 - 搭设开发环境

前言 Tauri框架结合了 Web 技术的优势&#xff0c;开发者能用熟悉的 HTML、CSS 和 JavaScript 进行开发&#xff0c;像开发网页应用一样便捷高效。 其次&#xff0c;该框架有着出色的性能表现&#xff0c;相比一些传统框架&#xff0c;其资源占用相对较低。在安全性方面&#x…...

tigase源码学习杂记-IO处理的线程模型

前言 tigase是一个高性能的服务器&#xff0c;其实个人认为作为即时通讯的服务器&#xff0c;高性能主要体现在他对IO复用&#xff0c;和多线程的使用上&#xff0c;今天来学习一下他的IO的线程处理模型的源码&#xff0c;并记录一下他优秀的设计。 概述 tigase是使用的NIO作…...

电商秒杀系统技术栈与难点解析 - Java架构师面试实战

电商秒杀系统技术栈与难点解析 - Java架构师面试实战 第一轮提问 面试官&#xff1a;马架构&#xff0c;欢迎参加我们公司的面试。首先&#xff0c;请您简单介绍一下自己。 马架构&#xff1a;您好&#xff0c;我叫马架构&#xff0c;拥有十年的Java研发经验和架构设计经验&…...

ASP.NET MVC​ 入门指南三

16. 安全性 16.1 身份验证和授权 身份验证&#xff1a;确认用户的身份。ASP.NET MVC 支持多种身份验证方式&#xff0c;如表单身份验证、Windows 身份验证和 OAuth 等。 表单身份验证&#xff1a;用户通过输入用户名和密码登录&#xff0c;服务器验证后颁发一个身份验证票证&…...

导览项目KD-Tree最近地点搜索优化

背景描述 我在做一个校园导览的小程序的时候&#xff0c;涉及到最近地点搜索的业务功能&#xff0c;根据当前位置搜索最近的校园地点&#xff0c;比如教学楼&#xff0c;图书馆&#xff0c;自习室&#xff0c;办事地点等等。 我最初想到的办法就是获取用户当前位置的经纬度后&…...

【Pandas】pandas DataFrame rmul

Pandas2.2 DataFrame Binary operator functions 方法描述DataFrame.add(other)用于执行 DataFrame 与另一个对象&#xff08;如 DataFrame、Series 或标量&#xff09;的逐元素加法操作DataFrame.add(other[, axis, level, fill_value])用于执行 DataFrame 与另一个对象&…...

苹果(IOS)手机怎么开启开发者模式(简单明了版)

苹果手机怎么开启开发者模式&#xff08;简单明了版&#xff09; iOS 16 以后&#xff0c;苹果新增了「开发者模式」。如果你要在 iPhone 上运行自己开发的 App&#xff0c;比如通过 Xcode 或其它工具安装测试包&#xff0c;必须先开启这个模式。 下面是开启方法&#x1f447…...

Agent2Agent

rag系列文章目录 文章目录 rag系列文章目录前言一、协议设计原则与技术基础二、通信机制与消息格式三、身份验证与安全设计四、能力发现与任务协作总结 前言 谷歌于2025年4月推出了A2A&#xff08;Agent2Agent&#xff09;协议&#xff0c;旨在解决当前AI智能体生态中的互操作…...

【MCP】了解远程MCP调用背后使用的SSE协议

本文介绍了远程MCP使用的SSE协议&#xff0c;通过wireshark抓包的方式了解MCP客户端和服务端之间通过SSE协议交互涉及到的请求与响应。 1. 什么是SSE协议&#xff1f; 参考&#xff1a;https://zhuanlan.zhihu.com/p/1894024642395619635和https://blog.csdn.net/aerror/artic…...

Log4j Properties 配置项详细说明

Log4j Properties 配置项详细说明 1. 核心配置项说明 根日志记录器&#xff1a;定义全局日志级别和输出目标 log4j.rootLogger [级别], appender1, appender2,...Appender 定义&#xff1a;指定日志输出目标&#xff08;控制台、文件等&#xff09; log4j.appender.[名称].[属…...