【Spring】Spring启示录

news2025/1/31 6:22:40

目录

前言

一、示例程序

二、OCP开闭原则

三、依赖倒置原则DIP

四、控制反转IOC

总结


前言

  在软件开发的世界里,随着项目的增长和需求的变化,如何保持代码的灵活性、可维护性和扩展性成为了每个开发者必须面对的问题。传统的面向过程或基于类的设计往往导致代码高度耦合,使得任何小的改动都需要对整个系统进行大规模的测试和调整。这不仅耗费时间,也增加了出错的风险。因此,理解并应用一些基本的设计原则,如开闭原则(OCP)和依赖倒置原则(DIP),对于构建高效、灵活的应用程序至关重要。本文将通过一个简单的用户登录示例,探讨如何从传统设计模式过渡到使用Spring框架实现控制反转(IoC)来解决这些问题,帮助开发者更好地理解和实践这些重要的编程理念。

一、示例程序

  当没有Spring时,我们是怎么开发的呢?我们先阅读下面的程序:

// 控制层
public class UserController {

    private UserService userService = new UserServiceImpl();

    public void login(){
        String username = "admin";
        String password = "123456";
        boolean success = userService.login(username, password);
        if (success) {
            // 登录成功
        } else {
            // 登录失败
        }
    }
}

// 业务层
public class UserServiceImpl implements UserService {

    private UserDao userDao = new UserDaoImplForMySQL();

    public boolean login(String username, String password) {
        User user = userDao.selectByUsernameAndPassword(username, password);
        if (user != null) {
            return true;
        }
        return false;
    }
}

// 数据库层
public class UserDaoImplForMySQL implements UserDao {
    public User selectByUsernameAndPassword(String username, String password) {
        // 连接MySQL数据库,根据用户名和密码查询用户信息
        return null;
    }
}

  可以看出,UserDaoImplForMySQL中主要是连接MySQL数据库进行操作。如果更换到Oracle数据库上,则需要再提供一个UserDaoImplForOracle。很明显,以上的操作正在进行功能的扩展,添加了一个新的类UserDaoImplForOracle来应付数据库的变化,这里的变化会引起连锁反应吗?当然会,如果想要切换到Oracle数据库上,UserServiceImpl类代码就需要修改。

二、OCP开闭原则

  上面的代码以及修改违背了OCP开闭原则,开闭原则是这样说的:在软件开发过程中应当对扩展开放,对修改关闭。也就是说,如果在进行功能扩展的时候,添加额外的类是没问题的,但因为功能扩展而修改之前运行正常的程序,这是忌讳的,不被允许的。因为一旦修改之前运行正常的程序,就会导致项目整体要进行全方位的重新测试。这是相当麻烦的过程。导致以上问题的主要原因是:代码和代码之间的耦合度太高。如下图所示:

 更多软件设计原则:【设计模式】软件设计原则-CSDN博客

  可以很明显的看出,上层是依赖下层的。UserController依赖UserServiceImpl,而UserServiceImpl依赖UserDaoImplForMySQL,这样就会导致下面只要改动上面必然会受牵连(跟着也会改),所谓牵一发而动全身。这样也就同时违背了另一个开发原则:依赖倒置原则。 

三、依赖倒置原则DIP

  依赖倒置原则(Dependence Inversion Principle),简称DIP,主要倡导面向抽象编程,面向接口编程,不要面向具体编程,让上层不再依赖下层,下面改动了,上面的代码不会受到牵连。这样可以大大降低程序的耦合度,耦合度低了,扩展力就强了,同时代码复用性也会增强(软件七大开发原则都是在为解耦合服务)。你可能会说,上面的代码已经面向接口编程了呀:

  确实已经面向接口编程了,但对象的创建是:new UserDaoImplForOracle()显然并没有完全面向接口编程,还是使用到了具体的接口实现类。什么叫做完全面向接口编程?请看以下代码:

  如果代码是这样编写的,才算是完全面向接口编程。那你可能会问,这样userDao是null,在执行的时候就会出现空指针异常呀。你说的有道理,确实是这样的,所以我们要解决这个问题。解决空指针异常的问题,其实就是解决两个核心的问题: 

  1. 谁来负责对象的创建。【也就是说谁来:new UserDaoImplForOracle()/new UserDaoImplForMySQL()】
  2. 谁来负责把创建的对象赋到这个属性上。【也就是说谁来把上面创建的对象赋给userDao属性】

  如果我们把以上两个核心问题解决了,就可以做到既符合OCP开闭原则,又符合依赖倒置原则。很荣幸的通知你:Spring框架可以做到。在Spring框架中,它可以帮助我们new对象,并且它还可以将new出来的对象赋到属性上。换句话说,Spring框架可以帮助我们创建对象,并且可以帮助我们维护对象和对象之间的关系。比如:

  Spring可以new出来UserDaoImplForMySQL对象,也可以new出来UserDaoImplForOracle对象,并且还可以让new出来的dao对象和service对象产生关系(产生关系其实本质上就是给属性赋值)。很显然,这种方式是将对象的创建权/管理权交出去了,不再使用硬编码的方式了。同时也把对象关系的管理权交出去了,也不再使用硬编码的方式了。像这种把对象的创建权交出去,把对象关系的管理权交出去,被称为控制反转。

四、控制反转IOC

  控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计思想,可以用来降低代码之间的耦合度,符合依赖倒置原则。控制反转的核心是:将对象的创建权交出去,将对象和对象之间关系的管理权交出去,由第三方容器来负责创建与维护。控制反转常见的实现方式:依赖注入(Dependency Injection,简称DI)。通常,依赖注入的实现又包括两种方式:

  • set方法注入
  • 构造方法注入

  Spring框架就是一个实现了IoC思想的框架。IoC可以认为是一种全新的设计模式,但是理论和时间成熟相对较晚,并没有包含在GoF中(GoF指的是23种设计模式)。

总结

  通过对一个简单用户登录系统的分析,我们了解到了在没有采用现代框架时开发可能面临的挑战:高耦合度的代码难以维护和扩展。遵循开闭原则(OCP)和依赖倒置原则(DIP),可以有效地降低这种耦合,提高代码的复用性和可扩展性。然而,手动管理对象创建和依赖关系仍然复杂且容易出错。Spring框架通过引入控制反转(IoC)概念,提供了一种优雅的解决方案。它不仅简化了对象的创建和依赖注入过程,还促进了更清晰、模块化的代码结构,极大地提升了开发效率和软件质量。掌握这些设计原则与技术框架的应用,可以帮助开发者构建更加健壮、灵活和易于维护的软件系统。

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

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

相关文章

八股——Java基础(四)

目录 一、泛型 1. Java中的泛型是什么 ? 2. 使用泛型的好处是什么? 3. Java泛型的原理是什么 ? 什么是类型擦除 ? 4.什么是泛型中的限定通配符和非限定通配符 ? 5. List和List 之间有什么区别 ? 6. 可以把List传递给一个接受List参数的方法吗? 7. Arra…

基于STM32的循迹小车设计与实现

1 系统方案设计 根据系统设计功能,展开基于STM32的循迹小车设计,整体设计框图如图2.1所示。系统采用STM32单片机作为控制器,通过L298驱动器控制两个直流电机实现对小车的运动控制,两路红外模块实现黑线的检测,HC-SR04超声波模块实…

AI刷题-蛋糕工厂产能规划、优质章节的连续选择

挑两个简单的写写 目录 一、蛋糕工厂产能规划 问题描述 输入格式 输出格式 解题思路: 问题理解 数据结构选择 算法步骤 关键点 最终代码: 运行结果:​编辑 二、优质章节的连续选择 问题描述 输入格式 输出格式 解题思路&a…

达梦拷贝DM_HOME的复制安装

近期一个项目需求,需要在没有安装包的情况下,将达梦数据库安装到虚机上(生产机上安装了达梦),故采用直接打包生产机DM_HOME的方式拷贝至虚机,再依次执行达梦的部分指令完成安装。以下为验证的步骤&#xff…

网络工程师 (3)指令系统基础

一、寻址方式 (一)指令寻址 顺序寻址:通过程序计数器(PC)加1,自动形成下一条指令的地址。这是计算机中最基本、最常用的寻址方式。 跳跃寻址:通过转移类指令直接或间接给出下一条指令的地址。跳…

第一届“启航杯”网络安全挑战赛WP

misc PvzHE 去这个文件夹 有一张图片 QHCTF{300cef31-68d9-4b72-b49d-a7802da481a5} QHCTF For Year 2025 攻防世界有一样的 080714212829302316092230 对应Q 以此类推 QHCTF{FUN} 请找出拍摄地所在位置 柳城 顺丰 forensics win01 这个软件 云沙盒分析一下 md5 ad4…

DeepSeek R1与OpenAI o1深度对比

文章目录 引言技术原理DeepSeek R1OpenAI o1 性能表现官方数据推理任务知识密集型任务通用能力 价格对比应用场景科研与技术开发自然语言处理(NLP)企业智能化升级教育与培训数据分析与智能决策 部署与集成DeepSeek R1OpenAI o1 伦理考量DeepSeek R1OpenA…

图漾Halcon版本SDK使用教程【V1.1.0新版本】

1.下载并安装 Halcon 1.1 下载Halcon软件 在 Halcon 官网(https://www.mvtec.com/downloads) 下载 Halcon (Windows 版) 安装包,并根据官方文档安装 Halcon,下载HALCON24.11Progress-Steady。 1.2 安装Halcon 1.解压HALCON 24.11.1.0的安装包压缩文件…

20.Word:小谢-病毒知识的科普文章❗【38】

目录 题目​ NO1.2.3文档格式 NO4.5 NO6.7目录/图表目录/书目 NO8.9.10 NO11索引 NO12.13.14 每一步操作完,确定之后记得保存最后所有操作完记得再次删除空行 题目 NO1.2.3文档格式 样式的应用 选中应用段落段落→开始→选择→→检查→应用一个一个应用ctr…

算法题(49):反转链表II

审题: 需要我们对指定范围的链表进行反转,并返回反转后链表的头结点 思路: 方法一:vector法 我们先遍历一次链表,并把数据对应的存在数组中,然后利用数组的reverse方法进行反转数据,最后再遍历一…

基于SpringBoot多数据源解决方案

最近在学习SpringBoot的时候,需要同时用两个不同的数据库连接服务,在网上学习了之后,下文以连接一个MySQL数据库和一个SqlServer数据库为例。 配置数据源连接信息 在配置文件中,配置对应的数据库连接信息,相比于单数…

通过案例研究二项分布和泊松分布之间关系(2)

通过案例研究二项分布和泊松分布之间关系 2. 汽车出事故的概率p与保险公司盈利W之间的关系3.通过遗传算法多次迭代计算控制p为多少时公司盈利最大(1) 计算过程(2) 结果及分析(计算过程详见附录二程序) 4.改变思路求解固定p为0.01时,保险费用如何设置公司可获得最大利润(1)计算过…

RISC-V读书笔记4

目录 乘法与除法 RV32F 和 RV32D:单精度和双精度浮点数 原子操作 压缩指令 向量 乘法与除法 RV32M属于扩展的指令,主要扩展的就是便捷的乘法和除法指令。 除法: 商 (被除数− 余数) 除数 被除数 除数 商 余数 余数 被除数− (商 …

【Uniapp-Vue3】request各种不同类型的参数详解

一、参数携带 我们调用该接口的时候需要传入type参数。 第一种 路径名称?参数名1参数值1&参数名2参数值2 第二种 uni.request({ url:"请求路径", data:{ 参数名:参数值 } }) 二、请求方式 常用的有get,post和put 三种,默认是get请求。…

大数据学习之SCALA分布式语言三

7.集合类 111.可变set一 112.可变set二 113.不可变MAP集合一 114.不可变MAP集合二 115.不可变MAP集合三 116.可变map一 package com . itbaizhan . chapter07 //TODO 2. 使用 mutable.Map 前导入如下包 import scala . collection . mutable // 可变 Map 集合 object Ma…

基于微信小程序的电子商城购物系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…

2000-2020年各省第二产业增加值占GDP比重数据

2000-2020年各省第二产业增加值占GDP比重数据 1、时间:2000-2020年 2、来源:国家统计局、统计年鉴 3、指标:行政区划代码、地区名称、年份、第二产业增加值占GDP比重 4、范围:31省 5、指标解释:第二产业增加值占GDP比重…

【Docker】Docker入门了解

文章目录 Docker 的核心概念Docker 常用命令示例:构建一个简单的 C 应用容器1. 创建 C 应用2. 创建 Dockerfile3. 构建镜像4. 运行容器 Docker 优势学习 Docker 的下一步 **一、Docker 是什么?****为什么 C 开发者需要 Docker?** **二、核心概…

java求职学习day18

常用的设计原则和设计模式 1 常用的设计原则(记住) 1.1 软件开发的流程 需求分析文档、概要设计文档、详细设计文档、编码和测试、安装和调试、维护和升级 1.2 常用的设计原则 (1)开闭原则(Open Close Principle…

初阶2 类与对象

本章重点 上篇1.面向过程和面向对象初步认识2.类的引入---结构体3.类的定义3.1 语法3.2 组成3.3 定义类的两种方法: 4.类的访问限定符及封装4.1 访问限定符4.2封装---面向对象的三大特性之一 5.类的作用域6.类的实例化7.类对象模型7.1 如何计算类对象的大小 8.this指…