当前位置: 首页 > news >正文

Spring基础及IoC容器的理解

Spring概念:

通常所说的Spring指的是Spring Framewprk(Spring框架),它是一个开源的框架。用一句话概括就是:Spring是包含了众多工具方法的IoC容器

什么是容器?

容器是用来容纳某种物品的装置,在之前的学习中,我们接触到的容器有List/Map(数据存储容器)Tomcat(Web容器)

什么是IoC容器?

Spring就是一个IoC容器,IoC(Inversion of Control)翻译成中文就是“控制反转”的意思,也就是说,Spring是一个“控制反转”的容器。

如何理解控制反转?

以前我们在一个类中使用另外一个类,需要New一个对象来使用,所以对象的生命周期是由当前代码或程序员来控制;控制反转其实是控制权反转,也就是说对象的生命周期,不由程序员或当前代码片段来控制,而是由Spring(Spring容器/IoC容器)来控制,这就叫做控制权反转。

为什么要使用IoC容器/Spring?

使用IoC容器最大的优点:可以实现解耦(松耦合)。
如何理解?我们可以想象成要造一辆车,要造这辆车得依赖于车身,车身又依赖于底盘,底盘依赖于轮胎。就像下面这张图所示:
在这里插入图片描述

下面我们用代码来演示这种关系:

传统的开发方式
  • 我们新建一个类,叫Car,这个类里面有一个init()方法,可以理解成造车的关键步骤,Car依赖于Framework类。
package old;public class Car {private  Framework framework;public  Car(){this.framework=new Framework();}public  void init(){System.out.println("执行了 Car  init方法");//依赖车身framework.init();}
}
  • 接着new一个Framework类,Framework依赖于Bottom。
package old;public class Framework {private  Bottom bottom;public  Framework(){this.bottom=new Bottom();}public  void  init(){System.out.println("执行了 Framework init 方法");//依赖底盘bottom.init();}
}
  • Framework又依赖于Bottom,于是我们再new一个Bottom类
package old;public class Bottom {private  Tire tire;public  Bottom(){this.tire=new Tire();}public  void init(){System.out.println("执行了 Bottom init 方法");//依赖轮胎tire.init();}
}
  • 最后new一个Tire类,定义属性size
package old;public class Tire {private  int size=20;public void init(){System.out.println("执行了Tire init 方法,Size:"+size);}
}
  • new一个Test类,测试一下代码是否正确:
package old;public class Test {public static void main(String[] args) {Car car=new Car();car.init();}
}

在这里插入图片描述
执行没有问题,上面的代码就是传统开发的过程。
但是如果对车的要求增加了,比如对于轮胎的size,不同的人群,对轮胎size大小要求不一样,在代码上体现就是不能再使用原来默认的size,我们Tire类中重载构造方法。

package old;public class Tire {private  int size=20;public  Tire(int size){this.size=size;}public void init(){System.out.println("执行了Tire init 方法,Size:"+size);}
}

但是这样会引发一系列的问题,Tire的构造方法是有参的,而Bottom又依赖于Tire,Bottom类也要随之改动,不然就会报错,就像下面这样:
在这里插入图片描述
我们先给Bottom补上需要的参数:

package old;public class Bottom {private  Tire tire;public  Bottom(int size){this.tire=new Tire(size);}public  void init(){System.out.println("执行了 Bottom init 方法");tire.init();}
}

Bottom中本身是没有参数size的,这里要改这个报错,需要传入size,于是这个size由Framework传入。Framework本身也没有size参数,于是需要Car传给它。

package old;public class Framework {private  Bottom bottom;public  Framework(int size){this.bottom=new Bottom(size);}public  void  init(){System.out.println("执行了 Framework init 方法");//依赖底盘bottom.init();}
}

当我们改完Framework类后,Car类也会出现问题,缺少size参数,我们重载Car的构造方法,进行有参构造传入size.

package old;public class Car {private  Framework framework;public  Car(int size){this.framework=new Framework(size);}public  void init(){System.out.println("执行了 Car  init方法");//依赖车身framework.init();}
}

然后我们在测试类中新建Car对象的时候设置size大小进行测试,我们把size设置成10:

package old;public class Test {public static void main(String[] args) {Car car=new Car(10);car.init();}
}

在这里插入图片描述
这样就可以随便设置轮胎size的大小,满足不同人群的需求。通过上面的代码可以可以看出,当我们最底层的代码发生改变时,整个调用链上的所有代码都需要改动,而且这只是改一个参数。那如果我们需要加别的参数并且做更改呢?这就非常麻烦,底层的代码改变,调用链上的所有代码都要跟着改变,这就是耦合———“牵一发而动全身”!
怎么解决这个问题呢?用IoC框架,使用IoC就可以实现解耦,就可以避免上面的问题。

IoC开发方式
  • 编写Car类,Car类依然依赖于Framework类,但是不同的是,我们使用Framework对象时不需要new了,直接声明一下,框架会给我们。
package ioc;
public class Car {private  Framework framework;public Car(Framework framework){this.framework=framework;}public  void  init(){System.out.println("Car init");framework.init();}
}
  • 编写Framework类,Framework依赖于Bottom,但是这里同样也没有new Bottom对象,同样是框架给我们的Bottom对象,直接去使用。
package ioc;public class Framework {private Bottom bottom;public Framework(Bottom bottom){this.bottom=bottom;}public  void  init(){System.out.println("Framework init");bottom.init();}
}
  • 编写Bottom类,Bottom依赖于Tire ,这里也没有new Tire对象,调用Tire时直接去框架中去取,然后给当前变量设置框架里面的bottom。
package ioc;public class Bottom {private  Tire tire;public  Bottom(Tire tire){this.tire=tire;}public  void  init(){System.out.println("Bottom init");tire.init();}
}
  • 编写Tire类,设置属性和init方法
package ioc;public class Tire {private   int size=15;public  Tire(){}public  void  init(){System.out.println("Tire init,size:"+size);}
}
  • 编写单元测试代码,这里是模拟Spring框架(不用关注这里的new对象),这是框架的事情。
package ioc;public class Test {private  Tire tire;private  Bottom bottom;private  Framework framework;private  Car car;public  Test(){this.tire=new Tire();this.bottom=new Bottom(this.tire);this.framework=new Framework(this.bottom);this.car=new Car(this.framework);}public static void main(String[] args) {Test test=new Test();test.car.init();}
}

在这里插入图片描述
然后我们给Tire设置size,将无参构造改成有参构造。

package ioc;public class Tire {private   int size=15;public  Tire(int size){this.size=size;}public  void  init(){System.out.println("Tire init,size:"+size);}
}

修改后整个调用链上的代码没有报错,调用链上的代码也不需要任何修改,Tire改动后哪里需要修改是Spring框架/IoC容器的事情,跟用户没有任何关系,Spring会自动去设置这些参数。
在这里插入图片描述
总结一下就是IoC帮我们实现了业务代码的解耦,实现了松耦合。不在是底层代码发生改变,整个调用链上的代码都要改变。这就是IoC的优点,实现解耦

相关文章:

Spring基础及IoC容器的理解

Spring概念: 通常所说的Spring指的是Spring Framewprk(Spring框架),它是一个开源的框架。用一句话概括就是:Spring是包含了众多工具方法的IoC容器。 什么是容器? 容器是用来容纳某种物品的装置,在之前的学习中&…...

护网行动为什么给的钱那么多

因为护网行动是国家应对网络安全问题所做的重要布局之一。 随着大数据、物联网、云计算的快速发展,愈演愈烈的网络攻击已经成为国家安全的新挑战。国家关键信息基础设施可能时刻受到来自网络攻击的威胁。网络安全的态势之严峻,迫切需要我们在网络安全领…...

软考知识汇总-计算机系统

文章目录 1 计算器 1 计算器 算术逻辑单元(ALU):运算器重要组成部件,负责处理数据,实现对数据的算数运算和逻辑运算。累加寄存器(AC):简称累加器,为ALU提供数据并暂存运…...

OpenCV 11(图像金字塔)

一、 图像金字塔 **图像金字塔**是图像中多尺度表达的一种,最主要用于图像的分割,是一种以多分辨率来解释图像的有效但概念简单的结构。简单来说, 图像金字塔是同一图像不同分辨率的子图集合. 图像金字塔最初用于机器视觉和图像压缩。其通过梯次向下采…...

Linux学习笔记-Ubuntu系统用户、群组、权限管理

一、概述 本文记录Ubuntu系统下通过命令操作用户账户进行管理。 Ubuntu系统版本: Linux ubuntu 5.15.0-1034-raspi #37-Ubuntu SMP PREEMPT Mon Jul 17 10:02:14 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux 注:查看系统版本号的指令如下 uname -…...

文章预览 安防监控/视频存储/视频汇聚平台EasyCVR播放优化小tips

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同,可实现视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、H.265自动转码H.264、平台级联等。为了便于用户二次开发、调用与集成,…...

Nand Flash的特性及烧录问题

目录 前言 一 Nand flash的特性 1 存储结构 2 OOB区域 3 位翻转 4 坏块及ECC 二 Nand系统裸片量产烧录 1 坏块处理策略 2 分区(Partition) 3 纠错码(Error Correction Codes,ECC) 4. 擦除坏块 🎈个人主页🎈:linux_嵌入式…...

【React 】useLayoutEffect 和 useEffect的区别

useLayoutEffect和useEffect是React中常用的两个Hook,它们的主要区别在于触发时机。 useEffect会在渲染完成后异步执行,不会阻塞浏览器的绘制操作。它适用于需要在组件渲染后执行副作用的情况,例如数据的获取、订阅事件等。它不会阻止屏幕更新…...

oracle数据库常见的优化步骤与脚本

要优化 Oracle 数据库的性能,可以按照以下步骤进行: 1. 性能分析和诊断:首先,使用 Oracle 提供的性能分析工具(如 AWR 报告、ASH 报告)对数据库进行分析和诊断。这些报告可以帮助您确定数据库的性能瓶颈和潜在问题。 2. 优化 SQL 查询语句:针对频繁执行的 SQL 查询语句…...

并发内存池(C++)

项目简介 这个项目是实现了一个高效的并发内存池。它的原型的goggle的一个开源项目tcmalloc,即thread-cache malloc(线程缓存的malloc),实现了高效多线程的内存管理,可实现对系统提供的内存分配函数malloc和free的替代…...

本地起一个VUE 前端项目

#安装 安装 Vue CLI 3: Vue CLI是一个用于创建和管理Vue项目的命令行工具 npm install -g vue/cli#查看更详细的告警信息 npm install -g vue/cli --verbose#检查项目的依赖关系 ,保持项目的依赖关系最新和安全 npm audit npm audit fix#查看版本 vue --version#创建…...

Python爬虫:Selenium的介绍及简单示例

Selenium是一个用于自动化Web应用程序测试的开源工具。它允许开发人员模拟用户在浏览器中的交互行为,以便自动执行各种测试任务,包括功能测试、性能测试和回归测试等。Selenium最初是为Web应用程序测试而创建的,但它也可用于Web数据抓取和其他…...

每日刷题|回溯法解决全排列问题第二弹之解决字符串、字母大小排列问题

食用指南:本文为作者刷题中认为有必要记录的题目 前置知识:回溯法经典问题之全排列 ♈️今日夜电波:带我去找夜生活—告五人 0:49 ━━━━━━️💟──────── 4:59 …...

python循环遍历字典: title_content_list.append([key, value])print(ti

示例示例Python循环遍历字典的方法有以下几种:使用for...in循环: Python循环遍历字典的方法有以下几种: 1. 使用for...in循环: python dict {name:Tom, age:20, gender:male} # 遍历所有的键 for key in dict:print(key) # 遍…...

Redis List类型命令 - Set类型命令 - SortedSet类型命令

目录 List类型 什么是双向链表呢? List类型的特征: List的常用命令 LPUSH和RPUSH的区别: LPOP和RPOP的区别: LPUSH和RPUSH的使用 LPOP和RPOP的使用 LRANGE key star end:返回一段距离范围内所有的元素 BLPOP…...

等级保护 —— 安全控制点,安全要求

等级保护 —— 安全控制点,安全要求 安全物理环境: 物理位置选择 a)机房场地应选择在具有防震、防风和防雨等能力的建筑内; 1)核查是否有建筑物抗震设防审批文档。2)核查是否有雨水渗漏的痕迹。3&#…...

nginx-缓存

disk cache:磁盘缓存数据,有时间延迟,但是非常小,相对于直接请求服务器返回 对于用户来说基本无感知。 memory cache:磁盘缓存数据,基本上没有时间延迟 协商缓存(nginx自带功能, 不…...

layui使用富文本已经使用第三方插件Kz.layedit来优化layui的富文本

官方提供的编辑器功能太少 没有字体颜色,不能传图片,视频等扩展 官方文档说的很清楚,简易的富文本使用layui提供的的确十分方便,但是缺少的元素很多。像什么标题,元素,等简单的都没有。小编我当初页为此苦…...

某公司二面面试题总结

你们公司开发遵守怎么样的代码规范? 当编写Java代码时,遵守良好的代码规范对于代码的可读性和可维护性至关重要。以下是一些更详细的Java代码规范建议: 命名规范: 类名应该采用名词或名词短语,使用驼峰命名法&#xf…...

Ubuntu编译运行socket.io

本篇文章记录一下自己在ubuntu上编译运行socket.io的过程,客户端选用的是socket.io的c的库,编译起来倒不难,但是说到运行的话,对我来说确实是花了点功夫。毕竟程序要能运行起来才能更方便地去熟悉代码,因此今天我就记录…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

条件运算符

C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...