Spring基础与核心概念

Spring 是什么?

我们通常所说的 Spring 指的是 Spring Framework(Spring 框架),它是⼀个开源框架,有着活跃而庞大的社区,这就是它之所以能长久不衰的原因。Spring 支持广泛的应⽤场景,它可以让 Java 企业级的应⽤程序开发起来更简单。
⽤⼀句话概括 Spring:Spring 是包含了众多工具方法的 IoC 容器。
那问题来了,什么是容器?什么是 IoC 容器?接下来我们⼀起来看。

什么是容器?

容器是⽤来容纳某种物品的(基本)装置。 ——来⾃:百度百科
我们想想,之前课程我们接触的容器有哪些?
List/Map -> 数据存储容器
Tomcat -> Web 容器
比如一个web,光有一个web的话是运行不起来的,你得需要把这个web放到toncat这个web容器上,才能运行起来

什么是 IoC?

Spring 也是⼀个容器,Spring 是什么容器呢?Spring 是⼀个 IoC 容器
什么是 IoC?
IoC = Inversion of Control 翻译成中⽂是“控制反转”的意思,也就是说 Spring 是⼀个“控制反转”的容器,由于这个“控制翻转”是英文直译过来的,有一些差别,实际上叫做控制(权)翻转
怎么理解这句话呢?
比如我们传统的java创建对象的方式是new一个新对象,这个对象的生命周期由我们程序员(当前代码)来控制的,因此我们就有了这个对象的控制权,什么是翻转呢?就是这个对象由被我们控制变成不被我们控制了,而是交给spring(也可以叫spring容器/IoC容器)来控制了,交给spring控制之后,我们不需要自己再new一个新对象了,只需要告诉spring我们要一个对象,它就会给我们一个
因此,控制权翻转可以理解为:对象的生命周期,不由程序员(或当前代码片段)来控制,而是由spring(也可以叫spring容器/IoC容器)来控制了

为什么要用IoC

IoC优点:可以实现解耦合(松耦合)

假如,我们现在构建⼀辆“⻋”的程序,我们的实现思路是这样的:
在这里插入图片描述
构建⼀辆⻋(Car Class),然⽽⻋需要依赖⻋身(FrameWork Class),⽽⻋身需要依赖底盘(BottomClass),⽽底盘需要依赖轮胎(Tire Class),最终程序的实现代码如下:

public class NewCarExample {public static void main(String[] args) {Car car = new Car();car.init();}/*** 汽⻋对象*/static class Car {public void init() {// 依赖⻋身Framework framework = new Framework();framework.init();}}/*** ⻋身类*/static class Framework {public void init() {// 依赖底盘Bottom bottom = new Bottom();bottom.init();}}/*** 底盘类*/static class Bottom {public void init() {// 依赖轮胎Tire tire = new Tire();tire.init();}}/*** 轮胎类*/static class Tire{// 尺⼨private int size = 30;public void init() {System.out.println("轮胎尺⼨:" + size);}}
}

以上程序中,轮胎的尺⼨的固定的,然⽽随着对的⻋的需求量越来越⼤,个性化需求也会越来越多,这时候我们就需要加⼯多种尺⼨的轮胎,那这个时候就要对上⾯的程序进⾏修改了,修改后的代码如下所示:

public class NewCarUpdateExample {public static void main(String[] args) {Car car = new Car(20);car.init();}/*** 汽⻋对象*/static class Car {private Framework framework;public Car(int size) {framework = new Framework(size);}public void init() {// 依赖⻋身framework.init();}}/*** ⻋身类*/static class Framework {private Bottom bottom;public Framework(int size) {bottom = new Bottom(size);}public void init() {// 依赖底盘bottom.init();}}/*** 底盘类*/static class Bottom {private Tire tire;public Bottom(int size) {tire = new Tire(size);}public void init() {// 依赖轮胎tire.init();}}/*** 轮胎类*/static class Tire {// 尺⼨private int size;public Tire(int size) {this.size = size;}public void init() {System.out.println("轮胎尺⼨:" + size);}}
}

从以上代码可以看出,以上程序的问题是:当最底层代码改动之后,整个调用链上的所有代码都需要修改
如何解决上述问题呢?
我们可以尝试不在每个类中自己创建下级类,如果自己创建下级类就会出现当下级类发⽣改变操作,自己也要跟着修改。
此时,我们只需要将原来由自己创建的下级类,改为传递的方式(也就是注入的方式),因为我们不需要在当前类中创建下级类了,所以下级类即使发生变化(创建或减少参数),当前类本身也无需修改任何代码,这样就完成了程序的解耦
PS:解耦指的是解决了代码的耦合性,耦合性也可以换⼀种叫法叫程序相关性。好的程序代码的耦合性(代码之间的相关性)是很低的,也就是代码之间要实现解耦。
这就好⽐我们打造⼀辆完整的汽车,如果所有的配件都是自己造,那么当客户需求发生改变的时候,比如轮胎的尺寸不再是原来的尺寸了,那我们要自己动⼿来改了,但如果我们是把轮胎外包出去,那么即使是轮胎的尺寸发⽣变变了,我们只需要向代理工厂下订单就行了,我们自身是不需要出⼒的。
基于以上思路,我们把调⽤汽⻋的程序示例改造⼀下,把创建⼦类的⽅式,改为注⼊传递的⽅式,具体实现代码如下

public class IocCarExample {public static void main(String[] args) {//以下四行是模拟spring ioc容器Tire tire = new Tire(20);Bottom bottom = new Bottom(tire);Framework framework = new Framework(bottom);Car car = new Car(framework);car.run();}static class Car {private Framework framework;public Car(Framework framework) {this.framework = framework;}public void run() {framework.init();}}static class Framework {private Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;}public void init() {bottom.init();}}static class Bottom {private Tire tire;public Bottom(Tire tire) {this.tire = tire;}public void init() {tire.init();}}static class Tire {private int size;public Tire(int size) {this.size = size;}public void init() {System.out.println("轮胎:" + size);}}
}

代码经过以上调整,⽆论底层类如何变化,整个调⽤链是不⽤做任何改变的,这样就完成了代码之间的解耦,从⽽实现了更加灵活、通⽤的程序设计了

在传统的代码中对象创建顺序是:Car -> Framework -> Bottom -> Tire
改进之后解耦的代码的对象创建顺序是:Tire -> Bottom -> Framework -> Car
在这里插入图片描述
我们发现了⼀个规律:通⽤程序的实现代码,类的创建顺序是反的,传统代码是 Car 控制并创建了Framework,Framework 创建并创建了 Bottom,依次往下,⽽改进之后的控制权发⽣的反转,不再是上级对象创建并控制下级对象了,⽽是下级对象把注⼊将当前对象中,下级的控制权不再由上级类控制了,这样即使下级类发⽣任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实现思想。
既然 Spring 是⼀个 IoC(控制反转)容器,重点还在“容器”⼆字上,那么它就具备两个最基础的功能:
将对象存⼊到容器;
从容器中取出对象。
也就是说学 Spring 最核心的功能,就是学如何将对象存⼊到 Spring 中,再从 Spring 中获取对象的过程。IoC容器管理的资源的是对象,对象在ioc的叫法叫Bean
将对象存放到容器中的好处:将对象存储在 IoC 容器相当于将以后可能⽤的所有⼯具制作好都放到仓库中,需要的时候直接取就⾏了,⽤完再把它放回到仓库。⽽ new 对象的⽅式相当于,每次需要⼯具了,才现做,⽤完就扔掉了也不会保存,下次再⽤的时候还得重新做,这就是 IoC 容器和普通程序开发的区别。

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

DI概念说明

说到 IoC 不得不提的⼀个词就是“DI”,DI 是 Dependency Injection 的缩写,翻译成中⽂是“依赖注入”的意思。
所谓依赖注⼊,就是由 IoC 容器在运⾏期间,动态地将某种依赖关系注⼊到对象之中。所以,依赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,就是指通过引⼊ IoC 容器,利⽤依赖关系注⼊的⽅式,实现对象之间的解耦
IoC 是“目标”也是⼀种思想,而目标和思想只是⼀种指导原则,最终还是要有可行的落地方案,而 DI就属于具体的实现。
比如说我今天心情比较好,吃⼀顿好的犒劳犒劳自己,那么“吃⼀顿好的”是思想和目标(是 IoC),但最后我是吃海底捞还是杨国福?这就是具体的实现,就是 DI
怎么理解:动态地将某种依赖关系注⼊到对象之中
这句话呢?
看下图
比如我在运行car类的时候,需要用到Framework这个类,现在我运行car了,ioc容器就知道我依赖的是framework这个对象,于是就可以在运行时候动态的把容器里的framework对象给car类里的framework对象,这样用到framework对象的时候就不至于是空指针异常了
在这里插入图片描述

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

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

相关文章

Android中级——PackageManagerService和Intent

PackageManagerService和Intent PackageManagerServiceIntent PackageManagerService PMS扫描已安装的apk,解析其AndroidManifest.xml获取App相关信息,如下是其构造函数的相关片段 ...... if (partition.getPrivAppFolder() ! null) { //扫描系统应用…

大数据Doris(一):Doris概述篇

文章目录 Doris概述篇 一、前言 二、Doris简介

【数据仓库设计基础(四)】数据仓库实施步骤

文章目录 1.定义范围2.确定需求3.逻辑设计1)建立需要的数据列表2)识别数据源3)制作实体关系图 4.物理设计1)性能优化2)数仓的拓展性 5.装载数据6.…

Vue封装全局SVG组件

1.SVG图标配置 1.安装插件 npm install vite-plugin-svg-icons -D 2.Vite.config.ts中配置 import { createSvgIconsPlugin } from vite-plugin-svg-icons import path from path export default () > {return {plugins: [createSvgIconsPlugin({// Specify the icon fo…

04. 人工智能核心基础 - 导论(3)

文章目录 人工智能和其他学科的关系为什么学习人工智能怎么学好人工智能?一些问题 Hi,你好。我是茶桁。 基于上一节课咱们的整体强度有点大,而且咱们马上也要进入高强度内容了,那么这一篇咱们就稍微水一篇吧。来聊聊天&#xff0…

FPGA 多路视频处理:图像缩放+视频拼接显示,HDMI采集,提供2套工程源码和技术支持

目录 1、前言版本更新说明免责声明 2、相关方案推荐FPGA图像缩放方案推荐FPGA视频拼接方案推荐 3、设计思路框架视频源选择IT6802解码芯片配置及采集动态彩条缓冲FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择 视频拼接算法图像缓存视频输出 4、vivado工程1&am…

【计算机网络】图解路由器(一)

本系列包含: 图解路由器(一)图解路由器(二) 图解路由器(一) 1、什么是路由器?2、什么是路由选择?3、什么是转发?4、路由器设备有哪些类型?5、根据…

创建vue3项目、链式调用、setup函数、ref函数、reactive函数、计算和监听属性、vue3的生命周期、torefs的使用、vue3的setup写法

1 创建vue3项目 # 两种方式- vue-cli:vue脚手架---》创建vue项目---》构建vue项目--》工具链跟之前一样- vite :https://cn.vitejs.dev/-npm create vuelatest // 或者-npm create vitelatest一路选择即可# 运行vue3项目-vue-cli跟之前一样-vite 创建的…

【小笔记】fasttext文本分类问题分析

【学而不思则罔,思维不学则怠】 2023.9.28 关于fasttext的原理及实战文章很多,我也尝试在自己的任务中进行使用,是一个典型的短文本分类任务,对知识图谱抽取的实体进行校验,判断实体类别是否正确,我构建了…

高级时钟项目(2)Json文件解析学习---C语言版本

笔者来介绍一下json文件解析 1、背景介绍 笔者在获取天气数据的时候,是通过MCU的WIFI去获取,但是获取到的数据json数据,需要解析,C语言没那么解析库,所以就需要找一些开源的解析库。 笔者找到cjson这个适用于C语言…

Vue - 组件递归

目录 组件递归子组件父组件 组件递归 当要渲染一个目录时,因为可能有嵌套数据,并且组件的层级未知,可以使用组件递归来解决 注意点: 1,使用递归时必须提供 name,也就是通过组件的 name 递归自己。 2&am…

Anaconda添加channels后出现unexpected urllib3 DEBUG logging from conda-build

1.问题描述 anaconda更新之后添加channels后出现bug: (base) ~/zlib-feedstock % conda build recipe 2>&1 | tee out ... INFO:conda_build.metadata:Attempting to finalize metadata for libzlib DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1):…

【c语言】通讯录【动态版本:有排序和文件操作】

目录 一、通讯录定义 二、通讯录的实现 1、test.c中菜单的实现 2、通讯录的创建逻辑 3、初始化 4、检查容量和添加 5、查找 6、删除功能 7、修改功能 8、打印 9、查找并打印 10、qsort排序 11、摧毁 12、保存数据到文件 13、从文件中读数据 完整代码: 一、通讯录定…

ABC310D Peaceful Teams

ABC310D Peaceful Teams 洛谷[ABC310D] Peaceful Teams 题目大意 有 n n n个运动员以及 m m m对数,每对数为 A i A_i Ai​和 B i B_i Bi​,表示 A i A_i Ai​和 B i B_i Bi​不能分在同一小组。你需要将这些人分为 t t t个小组,每个小组不…

【C++进阶(六)】STL大法--栈和队列深度剖析优先级队列适配器原理

💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C从入门到精通⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习C   🔝🔝 栈和队列 1. 前言2. 栈和队列的接口函数熟悉3. …

《淘宝电商业务场景》API接口教程获得淘口令真实url

淘口令API接口的本质就是一款调用相关技术的应用程序接口,同时也是一种通过互联网传输数据的方式,可以实现各种各样的应用场景。比如企业运用在分享商品页面的过程中,可以简单组成一个淘口令,以便于分享淘口令。淘口令解析API接口…

java easyexcel 导出多级表头

maven <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>${easyexcel.version}</version> </dependency> 导出行的对象 import com.alibaba.excel.annotation.ExcelIgnore; import …

基础算法--KMP字符串

KMP 算法是一个快速查找匹配串的算法&#xff0c;它的作用其实就是本题问题&#xff1a;如何快速在「原字符串」中找到「匹配字符串」。 在朴素解法中&#xff0c;不考虑剪枝的话复杂度是 O(m∗n) 的&#xff0c;而 KMP 算法的复杂度为 O(mn)。 KMP 之所以能够在O(mn) 复杂度内…

leetCode 213. 打家劫舍 II 动态规划 房间连成环怎么偷呢?

213. 打家劫舍 II - 力扣&#xff08;LeetCode&#xff09; 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 &#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#xff0c;相邻的房屋装…

websocket连接实例

websocket连接 此篇websocket是最简单的运用&#xff0c;虽然简单&#xff0c;但也是需要注意 还有其它方法货协议&#xff0c;比如socket.js等。今天时间不充裕虽然例子都写好了&#xff0c;下次更新websocket所有相关的东西。提前想了解的&#xff0c;可私信 前端 var webs…