【Spring】设计思想

一、Spring 是什么?

Spring是一个开源的Java框架,有着活跃而庞大的社区(例如:Apache),Spring 提供了一系列的工具和库,可以帮助开发者构建高效、可靠、易于维护的企业级应用程序。Spring的核心模块包括IOC容器、AOP、ORM等,它还提供了许多扩展模块如Spring MVC、Spring Security、Spring Data等,可以满足不同场景下的需求。Spring最初由Rod Johnson创建于2002年,如今已成为最流行、最广泛使用的Java开发框架之一。

用一句话概括 Spring : 包含了众多工具方法的 loC 容器。

框架是一种软件架构,是一组实现某种逻辑或功能的代码和类库的集合,我们需要按照框架设计者的规则来使用,所以在框架的世界里 :“约定大于配置”

“约定大于配置”(Convention over Configuration)是一种软件开发理念,通过使用一些约定过的默认设置和行为,来简化配置和编码的过程。在这种理念下,框架依据事先声明好的约定、继续一些默认设置和命名规则,自动完成一些繁琐的配置,使开发人员能够更快、更容易地构建应用程序。这样可以减少冗余代码以及重复劳动,帮助开发人员更好地专注于应用程序的功能开发。

举一个不大恰当的例子:就像我们使用的库函数一样,我们无需关注库函数的实现,我们关注的是这些库函数的应用场景是什么,有什么功能,我们怎么使用,参数是什么,函数的参数以及使用方式,就可以认为是函数与开发者的约定~

1.1 什么是 loC 容器

“容器” :可以存储一些东西的 “器物” 就叫做容器,例如水杯。

容器的概念,其实在JavaSE(语法) 阶段就接触过了,我们的集合类,ArrayLIst , Map ,Set 都是容器,是接纳数据的容器。

loC (In)Inversion of Control 翻译成中文就是 “控制反转” 的意思,控制反转一种编程设计思想,将程序的控制流程从传统的主动调用方式转变为被动接收方式,从而实现模块之间的解耦和依赖管理。

1.1.1 传统开发模型

假设,我们站在代码的角度构建一座房子, 设计思路:

 构建一座房子(House Class),然而房子需要依赖房屋结构(BuildingFame Class),而房屋构架需要依赖建筑材料(BuildingMaterials Class),而建筑材料需要依赖地基(FoundationClass),最终程序的实现代码如下:

//这是一个房子类
public class House {//一个房子需要依赖房屋的架构House() {System.out.println("这是一个房子");}BuildingFame buildingFame = null;public void init() {//依赖于房屋架构System.out.println("执行了初始化房屋架构的方法");this.buildingFame = new BuildingFame();buildingFame.init();}
}//房屋构架
class BuildingFame {//房屋的架构依赖与建筑材料BuildingMaterials buildingMaterials = null;public void init() {//依赖于建筑材料System.out.println("执行了初始化建筑材料的方法");this.buildingMaterials = new BuildingMaterials();buildingMaterials.init();}
}//建筑材料
class BuildingMaterials {//建筑材料依赖于地基Foundation foundation = null;public void init() {//依赖于地基System.out.println("执行了初始化地基的方法");this.foundation = new Foundation();foundation.init();}
}//地基
class Foundation {public void init() {String size = "100m*m";//依赖于地基System.out.println("地基:" + size);}
}

执行结果:

传统开发的缺陷:

以上程序中,房屋地基的大小(平方)的固定的,随着对的房屋的需求量越来越⼤,个性化需求也会越来越多,一个家庭人口多的可能需要 200 个平方的房子,对于新婚的夫妻来说也许 100 个平方的房子就够了,这时候我们针对房屋地基的大小进行处理了,同时也需要对上面的程序进⾏修改了,修改后的代码如下所示:

//这是一个房子类
public class House {//一个房子需要依赖房屋的架构House() {System.out.println("这是一个房子");}BuildingFame buildingFame = null;public void init(String size) {//依赖于房屋架构System.out.println("执行了初始化房屋架构的方法");this.buildingFame = new BuildingFame();buildingFame.init(size);}
}//房屋构架
class BuildingFame {//房屋的架构依赖与建筑材料BuildingMaterials buildingMaterials = null;public void init(String size) {//依赖于建筑材料System.out.println("执行了初始化建筑材料的方法");this.buildingMaterials = new BuildingMaterials();buildingMaterials.init(size);}
}//建筑材料
class BuildingMaterials {//建筑材料依赖于地基Foundation foundation = null;public void init(String size) {//依赖于地基System.out.println("执行了初始化地基的方法");this.foundation = new Foundation();foundation.init(size);}
}//地基
class Foundation {String size = "100 m*m";public void init(String size) {this.size = size;//依赖于地基System.out.println("地基:" + size);}
}

从上诉代码中可以看出的问题是:当最底层的代码需要改动时,整个 House 类调用链上的所有依赖类都需要进行修改,而且类于类之间的依赖性极高。

上述程序设计存在一定的缺陷,我们该如何解决呢?


1.1.2 loC 控制反转式程序开发

我们可以尝试不在每个类中创建下级类,如果创建的类出现当下级类发⽣改变操作,自己也要跟着修改的这种情况。这个时候,我们只需要将原来创建的下级类,改为传参的方式(也就是注⼊的方式),因为我们不需要在当前类中创建下级类了,当前类只是向外描述了我需要一个什么类,所以下级类即使发⽣变化(创建或减少参数),当前类本身也无需修改任何代码,这样就完成了程序的解耦。

说到这里儿,就不得不提一下啥是 “解耦”

高内聚低耦合(high cohesion and low coupling)是一种软件设计思想,可以有效地提高软件的可维护性和灵活性。

高内聚:指的是一个模块内部的元素彼此之间紧密相关,完成一个特定的、明确的任务,而不与其他外部元素产生过多的交互。

低耦合:指的是模块之间的相互依赖尽可能地低,模块之间只是完成部分纯粹的任务时才会进行互动,以减少相互影响,提高软件的灵活性和可扩展性。

使用高内聚低耦合的原则可以让软件系统更加灵活和易于维护。高内聚能够使得模块内部的逻辑更加清晰明确,每个模块都有特定的职责,易于理解和维护;低耦合能够降低模块之间的相互依赖,当需要修改或重构时,减少了对其他模块的影响,提高了软件的可维护性和可扩展性。

基于上述思路,我们把构建房屋的程序示例改造⼀下,把创建子类的方式,改为注入传递(传参)的方式,具体实现代码如下:

//这是一个房子类
public class House {BuildingFame buildingFame = null;//一个房子需要依赖房屋的架构public House(BuildingFame buildingFame) {this.buildingFame = buildingFame;System.out.println("这是一个房子");}public void init() {//依赖于房屋架构System.out.println("执行了初始化房屋架构的方法");buildingFame.init();}
}//房屋构架
class BuildingFame {//房屋的架构依赖与建筑材料BuildingMaterials buildingMaterials = null;public BuildingFame(BuildingMaterials buildingMaterials) {this.buildingMaterials = buildingMaterials;}public void init() {//依赖于建筑材料System.out.println("执行了初始化建筑材料的方法");buildingMaterials.init();}
}//建筑材料
class BuildingMaterials {//建筑材料依赖于地基Foundation foundation = null;public BuildingMaterials(Foundation foundation) {this.foundation = foundation;}public void init() {//依赖于地基System.out.println("执行了初始化地基的方法");foundation.init();}
}//地基
class Foundation {String size = "100 m*m";public Foundation(String size) {this.size = size;}public void init() {//依赖于地基System.out.println("地基:" + size);}
}

使用 loC 控制反转思想后, 无论被依赖类如何变化,对于整个调用链的影响是微乎其微的,这样就完成了代码之间的解耦,提高程序的灵活性和可扩展性。


小结:

通过以上两个实例,我们可以发现,两个实例类创建的顺序是反着的,传统的代码 House 控制并创建了 BuildingFame ,  BuildingFame 创建了 BuildingMaterials …… 依次往下创建,使用 loC 控制反转后,不再是上层对象创建并控制下层对象,而是把下层对象注入到当前对象中,这样下级类发生任何改变,也不会对当前类产生任何影响,这就是 loC 的实现思想。


1.2 Spring 是一个 loC 容器 

上文讲到,用一句话概括 Spring : 包含了多个工具方法的 loC 容器。博主也通过示例给大家阐述了什么是 loC (控制反转)思想。

重点还是在 “容器” 上,既然是一个容器,那么它就具备两个最基础的功能:

  • 将对象存入容器中;
  • 从容器中取出对象;

这也是 Spring 框架中最核心的功能,就是学会如何将对象存入到 Spring 中,如何从 Spring 中获取对象的过程。

将创建好的对象放在容器中的好处:对象存储在 loC 容器中,就好比将工具放在工具箱内,需要的时候直接从工具中取就好了,用完工具之后再放回工具箱中, new 对象的方式就好比,每次需要使用工具的时候发现没有,只能现场去“买一个”,用完之后也不保存,下次再需要的时候还得去“买”,这就是 loC 容器和普通程序开发的本质区别。

如何将对象存入到 Spring 中,如何从 Spring 中获取对象,将是下一期的核心,尽请期待。


1.3 DI 的概念

提起 loC 设计思想,就不得不提到 “DI” (Dependency Injection 的缩写——“依赖注入”

依赖注入” 指的就是由 IoC 容器在运行期间(程序运行期间),动态地将某种依赖关系注入到对象之中。传统的做法是由程序主动去找他所依赖的对象然后进行实例化,而DI则是由容器主动地将依赖关系注入到对象中。这样做的好处是对象之间解耦,提高了代码的复用性和可维护性。通过DI可以统一控制对象的生命周期,减少了资源的浪费。

站在广义的角度 loC 与 DI 描述的同一个东西,站在不同的角度 loC 是一种设计思想(控制反转)、指导原则,DI 则是 loC 思想的具体实现——IoC 容器在运⾏期间(程序运行期间),动态地将某种依赖关系注入到对象之中。

存放在 Spring 中的对象也被称之为 “Bean 对象”。

举个例子:我需要房子,

loC :我觉得盖一座房子需要 先打基地,在去买建筑材料,再把整个房子构架搭起来,装修慢慢搞,那么这是一种盖房子设计思想以及目的。

DI : 喂喂,张老板我想盖房子,你派挖掘机过来帮我挖一下地基,喂喂,李老板,我想盖房子,你帮我运些 沙石,钢筋混泥土过来…… ,喂喂,王老板,是这样的,我想盖个房子,你安排一下工人帮我盖房子呗,地基和建筑材料都已经到位了,价钱好商量。DI 是指导思想的具体是实现。


我与我周旋久,宁作我。

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

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

相关文章

短信压力测试系统,支持自定义接口

短信压力测试系统,支持自定义接口 支持卡密充值,短信压力测试系统,解决一切骚扰电话,教程在压缩包里面 可多个服务器挂脚本分担压力,套了cdn导致无法正常执行脚本可以尝试添加白名单 这边建议使用MySQL方式 同服务器下直接配置…

lesson 12 Zigbee绑定通信

目录 Zigbee绑定通信 通信原理 实验过程 实现步骤 实验现象 实验分析 Zigbee绑定通信 通信原理 1、Zigbee一共有五种通信方式:单播、广播、组播、MAC、广播 2、绑定是Zigbee的一种基本通信方式,具体绑定通信又分为三种模式,模式大同…

tomcat概述,优化,多实例部署

目录 一、概述 二、三个容器 1、Web 容器: 2、Servlet 容器: 3、JSP 容器: 三、Tomcat 功能组件结构 四、优化 1、启动速度优化 2、配置参数优化 五、多实例部署 一、概述 Tomcat 是 Java 语言开发的,Tomcat 服务器是一…

如何建立自己的知识体系?202209

知识太多了,无法全部快速吸收进大脑,需要通过特定的方法、技能,在面对大量知识的情况下,快速梳理,构建自己的知识体系。 学习的目标,不仅仅是记忆知识,而是搜索知识、并过滤、洞察、理解、使用…

搭建Hadoop高可用框架分布式集群

搭建Hadoop高可用框架分布式集群 一.基础配置 1.创建虚拟机,修改虚拟机的主机名 2.修改网络配置 master:192.168.6.200 slave1:192.168.6.201 slave2:192.168.6.202 3.互ping测试 4.sudo授权 5.安装vim编辑器 6.配置网络映射 master配置映射 master向slave1传递映…

大数据Doris(五十二):Doris数据导出案例和注意事项

文章目录 Doris数据导出案例和注意事项 一、Doris数据导出到HDFS案例 1、创建Doris表并插入数据 2、创建Export ,数据导出到 HDFS 3、查看任务 4、查看导出结果 二、Doris数据导出到本地案例 1、配置 fe.conf 2、Doris 数据导出到本地 三、注意事项 Doris数据导出案例…

Layui时间范围选择器,添加【本周、本月、本季度、本年等常用时间快捷键】

文章目录 1. 界面实现2. JS具体实现2.1 第一种实现2.2 第二种实现 1. 界面实现 <input id"Date_select" type"text" class"form-control" placeholder"请选择时间范围" style"border-radius: 4px;" /><input id&qu…

TypeScript - 函数(中)

目录 1、编写良好泛型函数的准则 1.1 向下推送类型参数 1.2 使用较少的类型参数 1.3 类型参数应出现两次 2、可选参数 3、回调中的可选参数 4、函数重载 5、重载签名和实现签名 6、写好重载 1、编写良好泛型函数的准则 编写泛型函数很有趣&#xff0c;并且很容易被类…

递归函数:

含义&#xff1a;自己调自己 递归三要素&#xff1a;定义函数、终止条件和等价关系式 小案例&#xff1a;排序 let arr1 [8, 8, 9, 13, 45, 8, 0, 1, 9, 66];//定义函数function quickSort(arr) {//终止条件if (arr.length < 1) return arr;const baseIndex Math.floor(…

uniapp顶部导航栏被遮住显示问题

解决uniapp顶部导航栏被遮住显示问题 uniapp官方给了处理的方案&#xff0c;即css变量&#xff0c;–status-bar-height&#xff0c;小程序这个值是25px&#xff0c;app则根据实际情况去变化 如下&#xff1a; //头部导航栏 <view class"header"> </view…

软件破解专题01

玩脱壳&#xff1f; 破解的功能&#xff1a;可以把收费软件免费使用 推荐论坛&#xff1a;pyg论坛》www.chinapyg.com 逆向&#xff1a;团队合作&#xff0c;有条件可以参加ctf大赛&#xff0c;这个应该是进步最快的途径 一个很强的开源项目&#xff1a;de4dot 作者…

Redis(主从复制、哨兵模式、集群)概述及部署

Redis&#xff08;主从复制、哨兵模式、集群&#xff09;概述及部署 一、Redis主从复制1、Redis主从复制的概念2、Redis主从复制的作用3、Redis主从复制的流程4、Redis主从复制的搭建 二、Redis 哨兵模式1、哨兵模式的原理2、哨兵模式的作用3、哨兵模式的结构4、哨兵模式的搭建…

springboot校园点餐小程序

校园点餐系统 springboot校园点餐系统小程序 java校园点餐小程序 技术&#xff1a; 基于springbootvue小程序校园点餐系统的设计与实现 运行环境&#xff1a; JAVA版本&#xff1a;JDK1.8 IDE类型&#xff1a;IDEA、Eclipse都可运行 数据库类型&#xff1a;MySql&#xff08;…

SpringSecurity(三):自定义认证数据源(源码+落地实现)。

自定义认证数据源 前言认证流程分析易混梳理AuthenticationManager 与 ProviderManagerProviderManager 与 AuthenticationProvider难点&#xff1a;为什么ProviderManager会有一个parent&#xff1f; 数据源的获取配置AuthenticationManager默认的全局 AuthenticationManager自…

SpringBoot源码分析(1)--@SpringBootApplication注解使用和原理/SpringBoot的自动配置原理详解

文章目录 前言主启动类的配置1、SpringBootApplication注解1.1、SpringBootConfiguration注解验证启动类是否被注入到spring容器中 1.2、ComponentScan 注解ComponentScan 注解解析与路径扫描 1.3、EnableAutoConfiguration注解1.3.1、AutoConfigurationPackage注解1.3.2、Impo…

YOLO系列正负样本分配策略

1、YOLOv3 使用MaxIoUAssigner策略来给gt分配样本&#xff0c;基本上保证每个gt都有唯一的anchor对应&#xff0c;匹配的原则是该anchor与gt的IOU最大且大于FG_THRESH&#xff0c;这种分配制度会导致正样本比较少&#xff0c;cls和bbox分支训练起来可能比较慢。在剩余的anchor…

【微服务架构模式】微服务设计模式

这是微服务架构系列文章的第 3 篇 高可用性、可扩展性、故障恢复能力和性能是微服务的特征。您可以使用微服务架构模式来构建微服务应用程序&#xff0c;从而降低微服务失败的风险。 模式分为三层&#xff1a; 应用模式 应用程序模式解决了开发人员面临的问题&#xff0c;例如数…

vue表格实现一个简单的合并单元格功能

用的是vue2ant-design-vue 但是vue3或者element-ui也是同理 先上效果 需要后端的数据将相同id的放在一起 否则也会有问题 例如&#xff1a; this.list [{id: 1,name: 舟山接收站,...}{id: 2,name: 舟山接收站碳中和LNG,...},{id: 2,name: 舟山接收站碳中和LNG,...} ]// th…

Java-数据结构(一)-java1中有哪些数据结构呢?

这里写目录标题 前言一、为什么需要数据结构&#xff1f;1、低效的操作2、占用过多的内存空间3、困难的数据操作 二、枚举&#xff08;Enumeration&#xff09;1、定义2、关键字3、适用场景 三、 位集合&#xff08;BitSet&#xff09;1、定义2、方法3、适用场景 四、向量&…

联邦学习 (FL) 中常见的3种模型聚合方法

联邦学习 (FL) 中常见的3种模型聚合方法 联合学习 (FL) 是一种出色的 ML 方法&#xff0c;它使多个设备&#xff08;例如物联网 (IoT) 设备&#xff09;或计算机能够在模型训练完成时进行协作&#xff0c;而无需共享它们的数据。 “客户端”是 FL 中使用的计算机和设备&#x…