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. 容器是什么?

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

Java 中也有一些容器,比如 List,Map,Set 等这些集合,是属于数据储存的容器,它把我们常用的操作都封装到集合中了,我们只需要知道集合为我们提供的方法就可以使用各种集合了;还有 Tomcat 是属于 Web 容器,同理 Spring 是就一个 IoC 容器,它包含了许多的工具和方法。

2. IoC是什么?

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

这种思想还比较抽象,我们来通过一个例子来了解它。

我们都知道汽车,它包含轮胎,底座,车身等,现在我们要造一辆汽车时,需要有车身,而车身需要有底座和轮胎,最传统的思想就是造车时,需要车身,于是就new一个车身,而车身需要底座,于是就再new一个底座,同理底座需要轮胎,那就造底座前new一个轮胎。
img

我们可以得到以下代码:

package old;/*** 传统开发方式, 耦合性问题*/
// 汽车类
public class Car {// 车身private Framework framework;public Car() {framework = new Framework();}public void init() {System.out.println("do car");// 汽车的组建依赖于车身framework.init();}
}package old;// 车身类
public class Framework {private Bottom bottom;public Framework() {bottom = new Bottom();}public void init() {System.out.println("do framework");// 车身的组建依赖于底盘bottom.init();}
}package old;// 底盘类
public class Bottom {private Tire tire;public Bottom() {tire = new Tire();}public void init() {System.out.println("do bottom");// 底盘的组建依赖于轮胎tire.init();}
}package old;// 轮胎类
public class Tire {private int size = 17; // 轮胎的尺寸public void init() {System.out.println("size -> " + size);}
}package old;public class Test {public static void main(String[] args) {Car car = new Car();car.init();}
}

但是,但上面的代码中,轮胎的大小是固定写死的, 然而随着对的车的需求量越来越大,个性化需求也会越来越多,这 时候我们就需要加⼯多种尺寸的轮胎,那这个时候就要对上面的程序进行修改了,根据我们上面写的代码,我们需要往轮胎Tire类的构造方法加上一个参数,由于底盘Bottom类控制着Tire类,那么底盘类的构造方法也需要加上一个参数,以此类推,我们的车身Framework类与汽车Car类都需要为构造方法加上参数,于是我们得到了如下的代码:

package old;/*** 传统开发方式, 耦合性问题*/
// 汽车类
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 old;// 车身类
public class Framework {private Bottom bottom;public Framework(int size) {bottom = new Bottom(size);}public void init() {System.out.println("do framework");// 车身的组建依赖于底盘bottom.init();}
}package old;// 底盘类
public class Bottom {private Tire tire;public Bottom(int size) {tire = new Tire(size);}public void init() {System.out.println("do bottom");// 底盘的组建依赖于轮胎tire.init();}
}package old;// 轮胎类
public class Tire {private int size = 17; // 轮胎的尺寸public Tire(int size) {this.size = size;}public void init() {System.out.println("size -> " + size);}
}package old;public class Test {public static void main(String[] args) {Car car = new Car(20);car.init();}
}

此时,如果需要个性化定制轮胎的大小,就可以只改动构造Car对象传入的参数就可以了;但是,如果再加上加上一个需求,还要定制轮胎的颜色,那我们又要加参数,此时就意味着像上面一样修改最底层的代码, 整个调⽤链上的所有代码都需要修改。

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

package ioc;public class Car {// 汽车的组建依赖于车身的组建private Framework franmework;public Car(Framework franmework) {this.franmework = franmework;}public void init() {System.out.println("do car...");franmework.init();}
}package ioc;public class Framework {// 车身的组建依赖于底盘private Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;}public void init() {System.out.println("do franmework");bottom.init();}
}package ioc;public class Bottom {// 底盘的组建依赖于轮胎private Tire tire;public Bottom(Tire tire) {this.tire = tire;}public void init() {System.out.println("do bottom...");tire.init();}
}package ioc;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 ioc;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 ioc;/*** 模拟 IoC 容器*/
public class Test {public static void main(String[] args) {// 直接使用, 创建就交给IoC了IOCDemo ioc = new IOCDemo();Car car = ioc.car;car.init();}
}

此时如果要变需求,需要加参数或减少参数,IoC 的代码只需改动图中的两处代码即可, 整个调用链是不用做任何改变的, 达到了解耦的目的。

img
img

在传统的代码中对象创建顺序是: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/1835.shtml

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

相关文章

数据结构_进阶(1):搜索二叉树

1.内容 建议再看这节之前能对C有一定了解 二叉树在前面C的数据结构阶段时有出过,现在我们对二叉树来学习一些更复杂的类型,也为之后C学习的 map 和 set 做铺垫 1. map和set特性需要先铺垫二叉搜索树,而二叉搜索树也是一种树形结构2. 二叉搜…

Stable Diffusion生成图片参数查看与抹除

前几天分享了几张Stable Diffusion生成的艺术二维码,有同学反映不知道怎么查看图片的参数信息,还有的同学问怎么保护自己的图片生成参数不会泄露,这篇文章就来专门分享如何查看和抹除图片的参数。 查看图片的生成参数 1、打开Stable Diffus…

Ubuntu 安装 Docker

本文目录 1. 卸载旧版本 Docker2. 更新及安装工具软件2.1 更新软件包列表2.2 安装几个工具软件2.3 增加一个 docker 的官方 GPG key2.4 下载仓库文件 3. 安装 Docker3.1 再次更新系统3.2 安装 docker-ce 软件 4. 查看是否启动 Docker5. 验证是否安装成功 1. 卸载旧版本 Docker …

【iOS】—— 属性关键字及weak关键字底层原理

文章目录 先来看看常用的属性关键字有哪些:内存管理有关的的关键字:(weak,assign,strong,retain,copy)关键字weak关键字assignweak 和 assign 的区别:关键字strong&#…

React(3)

1.案例选项卡 import React, { Component } from reactexport default class App extends Component {state{tabList:[{id:1,text:"电影"},{id:2,text:"影院"},{id:3,text:"我的"}]}render() {return (<div><ul>{this.state.tabList…

【LocalSend】开源跨平台的局域网文件传输工具,支持IOS、Android、Mac、Windows、Linux

工作前提条件&#xff1a;设备使用相同的局域网。 LocalSend is a cross-platform app that enables secure communication between devices using a REST API and HTTPS encryption. Unlike other messaging apps that rely on external servers, LocalSend doesn’t require …

【经济调度】基于多目标宇宙优化算法优化人工神经网络环境经济调度研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码及数据 &#x1f4a5;1 概述 基于多目标宇宙优化算法&#xff08;Multi-Objective Universe Optimization Algorithm, MOUA&#xff09;优化人工神经网络环境经济调度是一…

预付费电表收费系统

预付费电表收费系统是一种先进的电表管理系统&#xff0c;它能够帮助电力公司更加高效地管理电表收费&#xff0c;提高用电效率&#xff0c;降低能源浪费。本文将从以下几个方面介绍预付费电表收费系统的特点和优势。 一、预付费电表收费系统的原理 预付费电表收费系统是指用户…

Hadoop集群启动常见错误

错误一 &#xff1a; 配置文件错误 解决方案&#xff1a;检查配置文件&#xff0c;修改错误。重新分发&#xff08;同步&#xff09; 常见错误二 &#xff1a; 重复格式化 DataNode NameNode 在格式化时如果发现下面的提示说明重复格式化了 datanode和namenode的集群id…

Spring Cloud 远程接口调用OpenFeign负载均衡实现原理详解

环境&#xff1a;Spring Cloud 2021.0.7 Spring Boot 2.7.12 配置依赖 maven依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency&…

一百三十、海豚调度器——用DolphinScheduler定时调度HiveSQL任务

一、目标 用海豚调度器对Hive数仓各层数据库的SQL任务进行定时调度。比如&#xff0c;DWD层脱敏清洗表的动态插入数据、DWS层指标表的动态插入数据 二、工具版本 1、海豚调度器&#xff1a;apache-dolphinscheduler-2.0.5-bin.tar.gz 2、Hive&#xff1a;apache-hive-3.1.2…

长短期记忆网络(LSTM)原理解析

长短期记忆网络&#xff08;Long Short-Term Memory&#xff0c;简称LSTM&#xff09;是一种常用于处理序列数据的深度学习模型。它在循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;的基础上进行了改进&#xff0c;旨在解决传统RNN中的梯度消失…

PyTorch训练RNN, GRU, LSTM:手写数字识别

文章目录 pytorch 神经网络训练demoResult参考来源 pytorch 神经网络训练demo 数据集&#xff1a;MNIST 该数据集的内容是手写数字识别&#xff0c;其分为两部分&#xff0c;分别含有60000张训练图片和10000张测试图片 图片来源&#xff1a;https://tensornews.cn/mnist_intr…

Kafka消息监控管理工具Offset Explorer的使用教程

1、kafka监控管理工具 Offset Explorer是一款用于监控和管理Apache Kafka集群中消费者组偏移量的开源工具。它提供了一个简单直观的用户界面&#xff0c;用于查看和管理Kafka消费者组偏移量的详细信息。 Offset Explorer具有以下主要功能和特点&#xff1a; 实时监控&#x…

架构训练营学习笔记3-5:消息队列备选架构设计实战

本文属于架构训练营学习笔记系列&#xff1a;模块3的案例讲解 总的来说&#xff0c;这篇从更高的维度去讲&#xff0c;而不是关注消息队列的常见问题&#xff1a;比如消息如何发送&#xff0c;消息如何不丢失 &#xff0c;消息如何不重复。总体上分为2部分&#xff1a;利益干系…

【Docker】什么是Docker,它用来干什么

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…

ADB初识

ADB是Android Debug Bridge&#xff0c;是一个命令行程序。abd可以从计算机上通过USB控制Android手机设备。可以使用ADB复制文件、安装和卸载应用程序&#xff0c;运行shell命令等。 ADB的下载配置 Windows版本&#xff1a;https://dl.google.com/android/repository/platform…

2.SpringBoot运维实用篇

SpringBoot运维实用篇 ​ ​ 下面就从运维实用篇开始讲&#xff0c;在运维实用篇中&#xff0c;我给学习者的定位是玩转配置&#xff0c;为开发实用篇中做各种技术的整合做好准备工作。 主要分为以下内容&#xff1a; SpringBoot程序的打包与运行配置高级多环境开发日志 ​…

C国演义 [第十二章]

第十二章 打家劫舍题目理解步骤dp数组递推公式初始化遍历顺序 代码 打家劫舍II题目理解步骤递推公式初始化遍历顺序 代码 打家劫舍 力扣链接 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋…

《深度学习推荐系统》笔记

目录 一、推荐系统是什么1.作用和意义2.推荐系统的架构2.1 逻辑架构2.2 技术架构 二、传统的推荐系统方法1. 协同过滤算法1.1 userCF&&ItemCF1.3 矩阵分解算法 2. 逻辑回归算法3. 因子分解机3.1 POLY2模型3.2 FM模型3.3 FFM模型3.4 小结 4. 组合模型4.1 GBDTLR组合模型…