【JavaEE进阶】Spring核心与设计思想

文章目录

  • 一. Spring框架概述
    • 1. 什么是Spring框架
    • 2. 为什么要学习框架?
    • 3. Spring框架学习的难点
  • 二. Spring 核心与设计思想
    • 1. 什么是容器?
    • 2. 什么是IoC?
    • 3. Spring是IoC容器
    • 4. DI(依赖注入)
    • 5. DL(依赖查找)

一. Spring框架概述

1. 什么是Spring框架

我们通常所说的 Spring 指的是 Spring Framework(Spring 框架),它是⼀个开源框架,有着活跃⽽庞⼤的社区,这就是它之所以能⻓久不衰的原因.Spring ⽀持⼴泛的应⽤场景,它可以让 Java 企业级的应⽤程序开发起来更简单.
⽤⼀句话概括 Spring: Spring 是包含了众多⼯具⽅法的IoC容器.

2. 为什么要学习框架?

因为学习框架相当于从“小作坊”到“工厂”的升级,小作坊什么都要自己做,工厂是组件式装配,特点就是高效。框架更加易⽤,简单且高效.

Servlet有以下痛点:

  1. 添加外部 jar 不⽅便,容易出错,比如添加了⼀个不匹配的外部 jar 版本。
  2. 运行和调试的时候需要配置 Tomcat 不⽅便。
  3. 发布不方便,Servlet 项目必须依靠外置的 Tomcat(外置的 Web 容器)运行。
  4. 路由配置不方便,⼀个访问地址对应⼀个 Servlet 类。

而 Spring Boot 相比于 Servlet 具备以下优点:

  1. 快速添加外部 jar 包。
  2. 调试项目更方便,无需配置 Tomcat,点击“运行”按钮就可以直接运行项目,因为 Spring Boot
    内置了 Tomcat 容器可直接运行,但是 Servlet 需外挂 Tomcat。
  3. 发布项目更加方便,无需配置 Tomcat,使用 java -jar 方式就可以发布。
  4. 对象自动装配。
  5. 添加路由更加方便,无需每个访问地址都添加⼀个类。

3. Spring框架学习的难点

  1. 配置比较多。
  2. 需要⼤量的外部 jar 包,在下载时容易出错。
  3. 会涉及简单的软件⼯程的设计思想(分层思想:前后端的分层思想;后端工程的分层思想)。
  4. 知识点相对来说比之前的知识更加的分散,要仔细听才能搞懂各个知识点的逻辑关系。
  5. 要记的东西很多,所以要大量地重复练习才能记住,比如各种注解。

Spring框架基本学习应用路线:Spring全家桶(Spring/Spring Boot/Spring MVC) -> MyBatis -> Redis 等。

二. Spring 核心与设计思想

Spring 核心就是这么一句话:Spring 框架是包含了众多工具方法的 IoC 容器。

那么这句话怎么理解呢?什么是容器?什么又是 IoC?

1. 什么是容器?

容器是⽤来容纳某种物品的(基本)装置。 ——来⾃:百度百科

之前我们接触的容器有以下:

  • List/Map -> 数据存储容器
  • Tomcat -> Web 容器

Spring 是就一个 IoC 容器,它包含了许多的工具和方法.

2. 什么是IoC?

IoC : Inversion of Control 翻译成中⽂是“控制反转”的意思.这是一种思想,控制权反转,在 Java 的常规代码中,对象的生命周期,是由当前代码(程序员自己)控制的,而控制权反转就是对象的生命周期,不再由当前代码片段来控制,而是由 Spring(IoC 容器)来控制.

举个🌰:
我们都知道汽车包含轮胎,底盘,车身等.现在我们要造一辆汽车,需要有车身,而车身需要依赖于底盘.而底盘依赖于轮胎.
在这里插入图片描述
传统的思想中,在造车的时候需要车身,于是就new一个车身,而车身需要底盘,于是就再new一个底盘,底盘需要轮胎,于是就再new一个轮胎.

package oldCar;
//传统汽车制造
//汽车类
public class Car {//车身private Framework framework;public Car(){framework = new Framework();}public void init() {System.out.println("do car");// 汽车的组建依赖于车身framework.init();}
}
package oldCar;
//车身类
public class Framework {//底盘private Bottom bottom;public Framework(){bottom = new Bottom();}public void init() {System.out.println("do framework");// 车身的组建依赖于底盘bottom.init();}
}package oldCar;
//底盘类
public class Bottom {//车轮private Tire tire;public Bottom(){tire = new Tire();}public void init(){System.out.println("do Bottom");//底盘依赖于轮胎tire.init();}
}package oldCar;
//轮胎类
public class Tire {private int size = 17;//轮胎的尺寸public void init(){System.out.println("size -> " + size);}
}package oldCar;public class Test {public static void main(String[] args) {Car car = new Car();car.init();}
}

在这里插入图片描述
车轮为17寸的汽车制作完毕.但是上述代码中轮胎大小是写死的,随着时代发展,人们对车的需求量越来越大,个性化需求也会越来越多,这时候我们就需要加工多种尺寸的轮胎,此时就需要修改上述代码.我们需要给轮胎Tire类的构造方法加上一个参数.由于底盘Bottom类控制了Tire类,那么底盘类的构造方法也需要加上一个参数.以此类推,FreamworkCar类都需要在构造方法中加上一个参数.

package oldCar;
//传统汽车制造
//汽车类
public class Car {//车身private Framework framework;public Car(int size){framework = new Framework(size);}public void init() {System.out.println("do car");// 汽车的组建依赖于车身framework.init();}
}
package oldCar;
//传统汽车制造
//汽车类
public class Car {//车身private Framework framework;public Car(int size){framework = new Framework(size);}public void init() {System.out.println("do car");// 汽车的组建依赖于车身framework.init();}
}
package oldCar;
//传统汽车制造
//汽车类
public class Car {//车身private Framework framework;public Car(int size){framework = new Framework(size);}public void init() {System.out.println("do car");// 汽车的组建依赖于车身framework.init();}
}package oldCar;
//轮胎类
public class Tire {private int size = 17;//轮胎的尺寸public Tire(int size) {this.size = size;}public void init(){System.out.println("size -> " + size);}
}
package oldCar;public class Test {public static void main(String[] args) {Car car = new Car(20);car.init();}
}

在这里插入图片描述
车胎尺寸为20寸的汽车制作好了.此时如果需要定制不同轮胎大小的尺寸,只需要改动狗仔Cae对象传入的参数即可.但是,如果再加上一个需求,改变车身颜色,那我们又要加三叔,此时就意味着和上述代码一样修改每一层的代码,整个调用链上的代码都需要修改.

上述代码耦合度就太高了.为了解决这个问题,我们可以使用loC的思想来实现代码,将控制权交出去,也就是说,IoC模式下,我们不再自己构造创建对象.当我们需要轮胎Tire类时,你就给我传一个Tire对象,我们不去new一个Tire对象了,这样的话,就算在Tire类加参数也只需要改动Tire类的构造方法与相关执行方法与属性,顶多再改一下Tire对象的创建,同理其他类也一样,将对象作为参数传入到上级类的构造方法中去就行了,但此时其他类是不需要修改的,这个过程也叫做传入或注入。
在这里插入图片描述
由于我们创建Car时需要Framework,所以先要实例一个Framework对象,同理实例一个Framework对象需要Bottom对象,那么需先实例一个Bottom对象,一样,在实例Bottom对象之前需要实例一个Tire对象,于是需要先后创建Tire对象,Bottom对象,Framework对象后才能创建一个Car对象,我们可以得到如下的代码:

package newCar;public class Car {// 汽车的组建依赖于车身的组建private Framework franmework;public Car(Framework franmework) {this.franmework = franmework;}public void init() {System.out.println("do car...");franmework.init();}
}package newCar;public class Framework {// 车身的组建依赖于底盘private Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;}public void init() {System.out.println("do franmework");bottom.init();}
}package newCar;public class Bottom {// 底盘的组建依赖于轮胎private Tire tire;public Bottom(Tire tire) {this.tire = tire;}public void init() {System.out.println("do bottom...");tire.init();}
}package newCar;public class Tire {private int size = 17;private String color = "黑色";public Tire(int size, String color) {this.size = size;this.color = color;}public void init() {System.out.println("size -> " + size);System.out.println("color->" + color);}
}package newCar;public class IOCDemo {// 这里的内容包含就相当于是 IoC 容器做的事情// 对象的生命周期控制权就翻转给 IoC 容器了, 不再由程序员控制private Tire tire;private Bottom bottom;private Framework framework;public Car car;public IOCDemo() {tire = new Tire(17, "红色");bottom = new Bottom(tire);framework = new Framework(bottom);car = new Car(framework);}
}package newCar;/*** 模拟 IoC 容器*/
public class Test {public static void main(String[] args) {// 直接使用, 创建就交给IoC了IOCDemo ioc = new IOCDemo();Car car = ioc.car;car.init();}
}

此时如果要变需求,需要加参数或减少参数,IoC 的代码只需改动两处代码即可, 整个调用链是不用做任何改变的, 达到了解耦的目的。
在这里插入图片描述
在这里插入图片描述
在传统的代码中对象创建顺序是:Car -> Framework -> Bottom -> Tire
改进之后解耦的代码的对象创建顺序是:Tire -> Bottom -> Framework -> Car

到这里我们就可以发现,传统的代码类创建顺序是反着的,Car 控制 FrameWork,FrameWork 控制着 Bottom,Bottom 控制着 Tire;而改进之后的控制权发生了反转,是下层将对象注入到当前对象当中,下级的控制权不再由上级控制了,下级在发生改变时会将改变完成后的对象注入上级,这样上级就是不受影响的,这就是 IoC 的实现思想。

所以 IoC 有以下的优点:对象(Bean)的生命周期交给 IoC 框架维护,作为程序员无需关注,说白了就是程序员不需要关注对象创建、销毁时机以及对象的依赖关系,这些工作加个 IoC 框架(也就是 Spring)做就行,实现了代码的解耦,对象的使用更加方便高效。

3. Spring是IoC容器

Spring 框架就是包含了多个工具方法的 IoC 容器,既然是容器,那它就有存和取的功能,这也是 Spring 最核心的两个功能:

  1. 将 Bean(对象)存储到 Spring 容器中。
  2. 将 Bean(对象)从 Spring 容器中取出来。

将对象存放到容器有什么好处呢?
将对象存储到 IoC 容器相当于我们将所有可能用到的工具制作好都放到仓库,当我们需要使用时直接取即可,用完归还仓库;而 new 对象的方式相当于我们每次需要用工具的时候现场制作,制作完了扔掉,下次需要的时候重新做。

Spring 是⼀个 IoC 容器,说的是对象的创建和销毁的权利都交给 Spring 来管理了,它本身⼜具备了存储对象和获取对象的能力。

4. DI(依赖注入)

DI,即Dependency Injection,依赖注入。

所谓依赖注⼊,就是由 IoC 容器在运行期间,动态地将某种依赖关系注入到对象之中,在pom.xml有一个依赖项,就是用来导入外部的资源,而这里的依赖注入,导入的不是外部的资源,而是对象;当某个 Java 实例需要另一个 Java 实例时,创建被调用者的工作不是由调用者实现,而是由 Spring 容器来完成,然后注入调用者,因此称为依赖注入。

IoC 与 DI 的区别是什么?

依赖注入(DI)和控制反转(IoC)是从不同的角度的描述的同⼀件事情,就是指通过引入 IoC 容器,利用依赖关系注入的方式,实现对象之间的解耦。

IoC 是“目标”也是⼀种思想,而目标和思想只是⼀种指导原则,最终还是要有可行的落地方案,而 DI 就属于具体的实现;也就是说,IoC 是一种思想,而 DI 是 IoC 的一种实现。

5. DL(依赖查找)

DL,即Dependency Lookup,依赖查找,也是 IoC的一种实现。

依赖查找和依赖注入的区别在于,依赖注入是将依赖关系委托给容器,由容器来管理对象之间的依赖关系,容器外部是不关心这种依赖关系的,需要时由容器判断提供什么;而依赖查找是由对象自己来查找它所依赖的对象,容器只负责管理对象的生命周期,也就是说此时需要容器外部自己确定要容器提供哪种依赖关系;两者之间是主动和被动的区别。

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

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

相关文章

2023-08-07力扣今日五题

链接: 剑指 Offer 53 - II. 0~n-1中缺失的数字 题意: 如题 解: 长度n的递增数组里,要找0到n中没出现的那个数字,那么出现的下标是0到n-1,一一对应即可,都出现了就是n没有 实际…

RocketMQ第二课-核心编程模型以及生产环境最佳实践

一、回顾RocketMQ的消息模型 ​ 上一章节我们从试验整理出了RocketMQ的消息模型&#xff0c;这也是我们使用RocketMQ时最直接的指导。 二、深入理解RocketMQ的消息模型 1、RocketMQ客户端基本流程 <dependency><groupId>org.apache.rocketmq</groupId>&…

字母异位词分组 LeetCode热题100

题目 给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 思路 将字符串按字符升序排列后作为key&#xff0c;原字符串作为value存储到map上。 代码 class Solution…

高效构建 vivo 企业级网络流量分析系统

作者&#xff1a;vivo 互联网服务器团队- Ming Yujia 随着网络规模的快速发展&#xff0c;网络状况的良好与否已经直接关系到了企业的日常收益&#xff0c;故障中的每一秒都会导致大量的用户流失与经济亏损。因此&#xff0c;如何快速发现网络问题与定位异常流量已经成为大型企…

dubbo之基础知识

Dubbo 官网地址&#xff1a;Apache Dubbo Dubbo 是一款易用、高性能的 WEB 和 RPC 框架&#xff0c;同时为构建企业级微服务提供服务发现、流量治理、可观测、认证鉴权等能力、工具与最佳实践 作用 1.远程方法调用 2.容错和负载均衡 3.提供服务的自动注册与发现 为什么需要…

One-4-All: Neural Potential Fields for Embodied Navigation 论文阅读

论文信息 题目&#xff1a;One-4-All: Neural Potential Fields for Embodied Navigation 作者&#xff1a;Sacha Morin, Miguel Saavedra-Ruiz 来源&#xff1a;arXiv 时间&#xff1a;2023 Abstract 现实世界的导航可能需要使用高维 RGB 图像进行长视野规划&#xff0c;这…

【Spring】AOP切点表达式

文章目录 1、语法2、通配符3、execution4、within5、annotation6、args7、args8、bean9、this10、target11、target12、within13、表达式组合14、补充 1、语法 动作关键词(访问修饰符 返回值 包名.类/接口名 .方法名(参数)异常名) 举例&#xff1a; execution(public User c…

AIGC:【LLM(五)】——Faiss:高效的大规模相似度检索库

文章目录 一.简介1.1 什么是Faiss1.2 Faiss的安装 二.Faiss检索流程2.1 构建向量库2.2 构建索引2.3 top-k检索 三.Faiss构建索引的多种方式3.1 Flat &#xff1a;暴力检索3.2 IVFx Flat &#xff1a;倒排暴力检索3.3 IVFxPQy 倒排乘积量化3.4 LSH 局部敏感哈希3.5 HNSWx 一.简介…

Golang通过栈实现表达式运算(中缀表达式转后缀表达式解析语法)

Golang通过栈实现表达式运算(中缀表达式转后缀表达式解析语法) 需求背景&#xff1a;将string表达式数组 [title AUSU && ( header Wecome || brand ! AC68U )] 解析并使用ES查询得到运算结果。 分析&#xff1a;带有括号的表达式&#xff0c;需要根据优先级解析&a…

jvm的垃圾回收算法有哪些

jvm的垃圾回收算法有标记-清除、复制、标记-整理、分代回收算法&#xff0c;它们分别有不同的实现&#xff1a; 一、标记-清除算法 利用可达性分析算法分析之后&#xff0c;将未被标记的对象[即不可达对象]清除&#xff0c;以便回收它们所占用的内存。 缺点&#xff1a; 1、需…

flask------消息闪现 flash

1介绍 flask提供了一个非常有用的flash()函数&#xff0c;它可以用来“闪现”需要提示给用户的消息&#xff0c;比如当用户登录成功后显示“欢迎回来&#xff01;”。在视图函数调用flash()函数&#xff0c;传入消息内容&#xff0c;flash&#xff08;&#xff09;函数把消息存…

TPlink DDNS 内网穿透?外网访问设置方法

有很多小伙伴都想知道&#xff1a;TPlink路由器怎么设置DDNS内网穿透&#xff1f;今天&#xff0c;小编就给大家分享一下TPlink DDNS 外网访问设置方法&#xff0c;下面是图文教程&#xff0c;帮助新手快速入门DDNS设置。 本文介绍的是云路由器TP-LINK DDNS的设置方法。TP-LIN…

R-Meta分析教程

详情点击链接&#xff1a;R-Meta模型教程 一&#xff1a;Meta分析的选题与文献计量分析CiteSpace应用 1、Meta分析的选题与文献检索 1)什么是Meta分析&#xff1f; 2)Meta分析的选题策略 3)文献检索数据库 4)精确检索策略&#xff0c;如何检索全、检索准 5)文献的管理与…

浏览器同源策略

浏览器同源策略 同源策略&#xff1a;是一个重要的浏览器的安全策略&#xff0c;用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互 它能帮助阻隔恶意文档&#xff0c;减少可能被攻击的媒介 例如&#xff1a;被钓鱼网站收集信息&#xff0c;使用ajax发起…

DevOps系列文章之 Docker 安装 NFS 服务器

Docker 安装 NFS 服务器 环境&#xff1a; 192.186.2.105 NFS 服务器 192.168.2.106 Client 客户端 安装 一、服务器端 https://github.com/f-u-z-z-l-e/docker-nfs-server 1、创建目录 mkdir /nfsdata mkdir -p /docker/nfs/2、启动脚本 vim start.sh# 内容 docker run …

[国产MCU]-BL602开发实例-GPIO控制

GPIO与控制 文章目录 GPIO与控制1、GPIO介绍2、GPIO管理相关API介绍3、硬件准备4、软件准备5、代码实现3.1 GPIO输出3.2 GPIO输入3.3 GPIO中断BL602的GLB(Global Register)是芯片通用全局设定模块,主要包含了时钟管理、复位管理、总线管理、内存管理以及GPIO管理等功能。 本文…

shell脚本自动打包部署

1、安装git 2、使用Git克隆代码 3、安装Maven &#xff08;1&#xff09; tar -zxvf ** 解压文件 &#xff08;2&#xff09;修改配置 &#xff08;3&#xff09;source /etc/profile 重新加载一下文件 &#xff08;4&#xff09;mvn -version 查看版本号 已经安装成…

线程池的使用案例一

一、配置线程池 1、不推荐的方式 ExecutorService executorService Executors.newFixedThreadPool(); // 创建⼀个固定⼤⼩的线程池&#xff0c;可控制并发的线程数&#xff0c;超出的线程会在队列中等待&#xff1b; ExecutorService executorService Executors.newCache…

基于Java+SpringBoot+Vue的篮球竞赛预约平台设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

C# 简单模拟 程序内部 消息订阅发布功能

文章目录 前言模拟消息订阅发布使用注意事项 前言 我想做个简单的消息发布订阅功能&#xff0c;但是发现好像没有现成的工具类。要么就是Mqtt这种消息订阅发布。但是我只想程序内部进行消息订阅发布&#xff0c;进行程序的解耦。那没办法了&#xff0c;只能自己上了 模拟消息…