初识Spring
目录
1.Spring 基础
2.传统程序开发
3.IoC程序开发(解耦)
4.DI
4.1 IoC 和 DI 有什么区别
1.Spring 基础
Spring 指的是 Spring Framework(Spring 框架),它是⼀个开源框架,有着活跃⽽庞⼤的社区,这就是它之所以能⻓久不衰的原因。Spring ⽀持⼴泛的应⽤场景,它可以让 Java 企业级的应⽤程序开发起来更简单。
一句话概括:Spring 是包含了众多工具方法的 IoC 容器
容器:⽤来容纳某种物品的(基本)装置(例如:List/Map ---> 数据存储容器、Tomcat ----> Web 容器)
IoC:IoC = Inversion of Control 翻译成中⽂是“控制反转”的意思,也就是说 Spring 是⼀个“控制反转”的容器
控制(权)反转:对象的生命周期,不是由程序员(或当前代码片段)来控制,而是由 Spring(Spring 容器/ IoC容器)来控制
IoC最大的优点:可以实现解耦(松耦合)
2.传统程序开发
假如,我们现在构建⼀辆“⻋”的程序,我们的实现思路是这样的:

/*** 传统开发:汽车对象*/
public class Car {private Framework framework;//依赖车声,建立车身//在构造方法中 newpublic Car() {this.framework = new Framework();}public void init() {//依赖车身System.out.println("执行了 init 方法");framework.init();}
}
/*** 车身类*/
public class Framework {private Bottom bottom;public Framework() {this.bottom = new Bottom();}public void init() {//依赖底盘System.out.println("执行了 Framework init 方法");bottom.init();}
}
/*** 底盘类*/
public class Bottom {private Tire tire;public Bottom() {this.tire = new Tire();}public void init() {//依赖轮胎System.out.println("执行了 Bottom init 方法");tire.init();}
}
/*** 轮胎类*/
public class Tire {private int size = 15;public void init() {System.out.println("执行了 Tire init,Size:"+ size);}
}
这个时候我们执行这段代码:
public class Test {public static void main(String[] args) {Car car = new Car();car.init();}
}

上述代码中轮胎的尺寸是固定的,然而随着对的车的需求量越来越⼤,个性化需求也会越来越多,这 时候我们就需要加工多种尺⼨的轮胎,那这个时候就要对上面的程序进行修改:
注意每一类中size的改动
/*** 传统开发:汽车对象*/
public class Car {private Framework framework;public Car(int size) {this.framework = new Framework(size);}public void init() {//依赖车身System.out.println("执行了 init 方法");framework.init();}
}/*** 车身类*/
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();}
}/*** 底盘类*/
public class Bottom {private Tire tire;//Botton 中没有size参数,继续让别人传参数public Bottom(int size) {this.tire = new Tire(size);}public void init() {//依赖轮胎System.out.println("执行了 Bottom init 方法");tire.init();}
}/*** 轮胎类*/
public class Tire {private int size = 15;//传递 size 参数public Tire(int size) {this.size = size;}public void init() {System.out.println("执行了 Tire init,Size:"+ size);}
}public class Test {public static void main(String[] args) {Car car = new Car(20);car.init();}
}

这个时候我们发现,虽然我们可以改变轮胎的尺寸,但是最底层代码改动之后,整个调用链上的所有代码都需要修改——耦合性问题
需求指挥越来越多,改动的也会越来越多,这个时候我们就可以使用 IoC 进行解耦
3.IoC程序开发(解耦)
/*** IoC:汽车对象*/
public class Car {private Framework framework;//初始化(不是用传统开发):让框架传入(不管咋样传入),声明使用Framework//如果是一个IoC框架,运行代码,会拿到当前框架中的Framework 赋值到当前变量中就会有 frameworkpublic Car(Framework framework) {this.framework = framework;}public void init() {System.out.println("Car init");framework.init();}
}public class Framework {private Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;}public void init() {System.out.println("Framework init");bottom.init();}
}public class Bottom {private Tire tire;public Bottom(Tire tire) {this.tire = tire;}public void init() {System.out.println("Bottom init");tire.init();}
}public class Tire {private int size = 15;public Tire() {}public void init() {System.out.println("Tire init, Size:" + size);}
}/*** 模拟 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 类中的尺寸:
public class Tire {private int size = 15;public Tire(int size) {this.size = size;}public void init() {System.out.println("Tire init, Size:" + size);}
}
这个时候只需要改 IoC 容器(Spring 框架 )即可(IoC 与用户没有关系),Spring 框架会自动设置参数
public class Test {private Tire tire;private Bottom bottom;private Framework framework;private Car car;public Test() {this.tire = new Tire(20);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();}
}

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

对比传统:
通⽤程序的实现代码,类的创建顺序是反的,传统代码是 Car 控制并创建了Framework,Framework 创建并创建了 Bottom,依次往下,⽽改进之后的控制权发⽣的反转,不再是上级对象创建并控制下级对象了,⽽是下级对象把注⼊将当前对象中,下级的控制权不再由上级类控制了,这样即使下级类发⽣任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实现思想。
既然 Spring 是⼀个 IoC(控制反转)容器,重点还在“容器”⼆字上,那么它就具备两个最基础的功能:
- 将对象存入到容器
- 从容器中取出对象
也就是说学 Spring 最核心的功能,就是学如何将对象存入到 Spring 中,再从 Spring 中获取对象的过程
将对象存放到容器中的好处:将对象存储在 IoC 容器相当于将以后可能⽤的所有共具制作好都放到仓库中,需要的时候直接取就行了,用完再把它放回到仓库。而new 对象的方式相当于,每次需要工具了,才现做,用完就扔掉了也不会保存,下次再⽤的时候还得重新做,这就是 IoC 容器和普通程序开发的区别
4.DI
DI 是 Dependency Injection 的缩写,翻译成中文是“依赖注入”的意思:指的是由 IoC 容器在运行期间,动态的将依赖对象获取到的过程
public class Car {private Framework framework;public Car(Framework framework) {this.framework = framework;}public void init() {System.out.println("Car init");framework.init();}
}
在运行 Car 时,动态的将 Framework 拿到当前类中的过程就叫做 依赖注入 (在运行类的时候,需要有一个依赖类,依赖类就会从容器中动态的查询出来,赋值给变量,就可以直接使用这个方法)
所以,依赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,就是指通过引⼊ IoC 容器,利⽤依赖关系注⼊的⽅式,实现对象之间的解耦;
IoC 是“目标”也是⼀种思想,而目标和思想只是⼀种指导原则,最终还是要有可行的落地方案,而 DI 就属于具体的实现。
比如说我今天吃⼀顿美餐,那么“美餐”是目标(是 IoC),但最后我是吃火锅还是烧烤?这就是具体的实现,就是DI
4.1 IoC 和 DI 有什么区别
IoC 和 DI 都是 Spring 框架中的核心概念,它们的区别在于:
- IoC(Inverse of Control,控制反转):它是一种思想,主要解决程序设计中的对象依赖关系管理问题。在 IoC 思想中,对象的创建权反转给第三方容器,由容器进行对象的创建及依赖关系的管理。
- DI(Dependency Injection,依赖注入):它是 IoC 思想的具体实现方式之一,用于实现 IoC。在 Spring 中,依赖注入是指:在对象创建时,由容器自动将依赖对象注入到需要依赖的对象中。
简单来说,它们的关系是:
- IoC 是一种思想、理念,定义了对象创建和依赖关系处理的方式。
- DI 是 IoC 思想的具体实现方式之一,实际提供对象依赖关系的注入功能。
所以 IoC 是更基础和广义的概念,DI 可以说是 IoC 的一种实现手段。大多数情况下,我们提到 IoC 的时候,其实意味着 DI,因为 DI 已经是 IoC 最常见和广泛使用的实现方式了。
例如在 Spring 框架中:
- IoC 体现为 Spring 容器承担了对象创建及依赖关系管理的控制权。
- DI 体现为 Spring 容器通过构造方法注入、Setter 方法注入等方式,将依赖对象注入到需要依赖的对象中。
所以综上,IoC 和 DI 之间的关系可以这样理解:
- IoC 是理论,DI 是实践。
- IoC 是思想,DI 是手段。
- IoC 是整体,DI 是部分。
相关文章:
初识Spring
目录 1.Spring 基础 2.传统程序开发 3.IoC程序开发(解耦) 4.DI 4.1 IoC 和 DI 有什么区别 1.Spring 基础 Spring 指的是 Spring Framework(Spring 框架),它是⼀个开源框架,有着活跃⽽庞⼤的社区&…...
Mybatis 使用参数时$与#的区别
之前我们介绍了mybatis中参数的使用,本篇我们在此基础上介绍Mybatis中使用参数时$与#的区别。 如果您对mybatis中参数的使用不太了解,建议您先进行了解后再阅读本篇,可以参考: Mybatis参数(parameterType)https://blog.csdn.net…...
解锁Spring Boot的强大配置功能:@ConfigurationProperties与@PropertySources详解
解锁Spring Boot的强大配置功能:ConfigurationProperties与PropertySources详解 前言什么是ConfigurationProperties和PropertySourcesConfigurationProperties的使用步骤 1: 创建 Java POJO 类步骤 2: 配置类步骤 3: 配置文件步骤 4: 注入配置属性 PropertySources…...
Java和Vue字符串加密
字符串加密 AES 加密算法 在 Java 中,可以使用不同的加密算法来对字符串进行加密。以下是使用 AES 加密算法的示例代码,演示如何对一个字符串进行加密: import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java…...
Java:java版结巴分词:jieba-analysis
文档 https://github.com/huaban/jieba-analysishttps://mvnrepository.com/artifact/com.huaban/jieba-analysis 依赖 <!-- https://mvnrepository.com/artifact/com.huaban/jieba-analysis --> <dependency><groupId>com.huaban</groupId><art…...
java生成一个符合密码学和安全性的随机秘钥
有时 我们在生成token 或者完成某种加密形式时会需要一个秘钥 但是 有些时候 项目开发并没有规定用什么秘钥 但是 秘钥都是要有一定格式规范的 我们可以通过以下代码生成一个随机秘钥 import java.security.SecureRandom; import java.util.Base64;public class TokenGenerat…...
C++ - 右值引用 和 移动拷贝
右值引用 我们先来了解什么是左值,什么是右值: 左值 和 有值 区分 首先,左值 和 右值 并不是完全意味着 在 "" 左边的就是 左值 ; 在 "" 右边的就是右值。这是不一定的。只能说,在左边的大概率是…...
项目成员积分规则
在当下的项目/团队管理种,如何让成员能清晰的看到,自己的工作、努力在团队种属于那个段位,通过这个形式,并配合其他方式去点燃成员的进步之心。以积分的形式,代替绩效考核,一些零散的想法,欢迎各…...
Linux CentOS7 vim多窗口编辑
我们在用vim编辑文件时,有各种需求。如有时需要在多个文件之间来回操作,一会关闭一个文件,一会再打开另外一个文件,这样来回操作显得太笨拙。有时,vim编辑多行的大文件,来回查看、编辑前面一部分及最后一部…...
git使用,一点点
查看自己有没有安装git git --version 如果没有安装请执行sudo yum install -y git来安装 git 指令 git log 查看日志 git pull 同步远端和本地仓库 这就是冲突的报错: 所以这个时候你要同步一下git pull...
第五章:最新版零基础学习 PYTHON 教程—Python 字符串操作指南(第八节 - 如何在 C/C++、Python 和 Java 中分割字符串?)
通过某些分隔符分割字符串是一项非常常见的任务。例如,我们有一个文件中以逗号分隔的项目列表,并且我们希望数组中包含各个项目。 几乎所有编程语言都提供按某些分隔符分割字符串的函数。 目录 在C中: 在 C++ 中 方法一:使用C++的stringstream API...
【Java】语法特性篇
语法特性篇 Java对象的比较 1. 对象比较的问题 Java中引用类型的变量不能直接按照 > 或者 < 方式进行比较。那为什么可以比较? 因为:对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equal方法…...
Vim教程
目录 vim 介绍 常用的四种模式 首先先学会如何正确进入和退出vim: normal模式 insert模式: command模式: v-block模式: vim异常退出 vim配置 vim 介绍 Vim是一款高度可定制的文本编辑器,它的前身是Vi…...
selenium查找网页如何处理网站资源一直加载非常卡或者失败的情况
selenium查找网页如何处理网站资源一直加载失败的情况 selenium获取一个网页,某个网页的资源卡了很久还没有加载成功,如何放弃这个卡的数据,继续往下走 有2钟方式。通常可以采用下面的方式一来处理这种情况 方式一、WebDriverWait 这种方式…...
并发工具类库使用的常见问题
一、ThreadLocal在多线程环境中没有清理 由于ThreadLocal是和线程绑定的,如果线程被复用了,也即使用了线程池,那么ThreadLocal中的值是可能被复用的,这个特性如果是开发者没有预料到的,那么会产生很大的问题。例如&am…...
GD32F10X ----RTC
1. RTC的简介 STM32 的实时时钟(RTC)是一个独立的定时器。STM32 的 RTC 模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。 RTC 模块和时钟配置…...
使用UiPath和AA构建的解决方案 1. 机器人过程自动化入门
你好!在这本系列,我们将指导您完成一些真实世界的机器人过程自动化(RPA)项目。感谢您的加入。当你完成本系列时,你将具备使用UiPath和Automation Anywhere在最低指导下进行简单到中等复杂度RPA项目的知识、技术和心态。 RPA是一项令人兴奋的新技术,被视为使用新的先进技…...
rust字面量
字面量就是值。值最终必须编码成二进制存储在某块内存上。 变量与字面量的关系就像杯子和水的关系。 字面量是有类型的。字面量类型有:布尔、数字、文本、字节 一、布尔 类型是bool true false 二、数字 通过后缀表示类型 通过前缀表示进制 通过 “_” 来分割数…...
Unix Network Programming Episode 79
‘gai_strerror’ Function The nonzero error return values from getaddrinfo have the names and meanings shown in Figure 11.7. The function gai_strerror takes one of these values as an argument and returns a pointer to the corresponding error string. #incl…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
