【Spring】什么是Spring?

什么是Spring?
Spring是一个开源的轻量级框架,是为了简化企业级开发而设计的。我们通常讲的Spring一般指的是Spring Framework。Spring的核心是控制反转(IoC-Inversion of Control)和面向切面编程(AOP-Aspect-Oriented Programming)。这些功能使得开发者可以专注于业务逻辑的实现,不用去关注底层的实现。除此之外,Spring还可以与第三方库和框架集成,如Mybatis等,使得我们开发更加方便。
我们来看看官方的解释:
Spring | Why Spring


可以看到,spring包含了很多模块,简单来说:Spring是包含了很多工具方法的IoC容器。
什么是容器?
Spring容器是Spring框架中的核心组成部分,负责管理Spring Bean的生命周期和依赖关系,Spring容器是一个BeanFactory(Bean工厂),负责实例化、配置和管理Bean。
在Spring程序中,我们所有的Bean都是存放在容器中,通过IoC(控制反转)技术进行管理。Spring容器通过自动装配(autowiring)的方式将各个Bean之间建立联系,从而减少手动配置的工作量。同时,Spring容器还提供了丰富的扩展机制,使得开发者可以根据自己的需求对bean进行定制化配置。
什么是IoC?
Spring IoC(控制反转),是一种设计思想,通过将对象的创建和管理权交给了Spring容器,降低了程序之间的耦合性,
在Spring框架中,IoC主要通过XML配置文件、注解或Java配置等方式实现。通过使用IoC,应用程序的各个模块之间就可以以低耦合的形式进行协同工作,提高应用程序的可扩展性和可维护性。
传统程序开发流程
我们来举个例子,来更好的理解上面所述内容。
假设我们现在要生产一辆车,其基本思路如下:

按照传统的做法,我们生产一辆车,车的构成需要依赖车身(Framework),而车身需要依赖底盘(Bottom),底盘需要依赖轮胎(Tire)。
按照这种思路,我们用代码实现如下:
public class CarProduct {public static void main(String[] args) {Car car = new Car();car.init();}/*** 汽车对象*/static class Car {private Framework framework;public Car() {framework = new Framework();}public void init() {framework.init();}}/*** 车身Framework*/static class Framework {private Bottom bottom;public Framework() {bottom = new Bottom();}public void init() {bottom.init();}}/*** 底盘Bottom*/static class Bottom {private Tire tire;public Bottom() {tire = new Tire();}public void init() {tire.init();}}/*** 轮胎Tire*/static class Tire {private int size = 20;//轮胎大小public void init() {System.out.println("轮胎大小:" + size);}}
}
我们可以看到,在上面的代码中,轮胎的尺寸是固定的,但是现在车的数量非常多,车轮胎的尺寸不可能都是一样的,所以我们就需要生产出各种尺寸大小的轮胎。我们需要对上面的代码进行修改:
public class CarProduct {public static void main(String[] args) {Car car = new Car();car.init(10);}/*** 汽车对象*/static class Car {private Framework framework;public Car() {framework = new Framework();}public void init(int size) {framework.init(size);}}/*** 车身Framework*/static class Framework {private Bottom bottom;public Framework() {bottom = new Bottom();}public void init(int size) {bottom.init(size);}}/*** 底盘Bottom*/static class Bottom {private Tire tire;public Bottom() {tire = new Tire();}public void init(int size) {tire.init(size);}}/*** 轮胎Tire*/static class Tire {public void init(int size) {System.out.println("轮胎大小:" + size);}}
}
我们可以看到,虽然满足我们的需求了,但是在上面的代码中,不难看到,当最底层的代码修改后,整个调用链上的代码都需要进行修改,这样耦合度就非常高了。
那么如果解决上面出现的这种问题呢?
在上面的代码中,我们都是在每个类中创建下一个要调用的类,这样的耦合度就非常高。
那么我们可以不在类中创建下级类,而是改为传递的方式(即注入),这样我们就能实现解耦,下级类的改变发生变化,对于当前类来说,也无需修改任何代码。
解耦指的是:解决了代码之间的依赖程度,也可以叫做程序相关性,好的程序的代码的耦合性是很低的,也就是代码之间要解耦。
这就好比我们生产一辆汽车,如果所有的配件都是自己制造的,那么当客户要改变需求时,如,客户想要一个比较大的轮胎,那么我们就需要自己生产,这样的效率是非常低的,但如果我们把轮胎的生产外包出去,那么就算轮胎的尺寸要发生改变,我们也能向代理公厂下单即可,无需自己生产,这样效率就提高了不少。
控制反转程序开发流程(IoC)
根据上面所述,对代码进行修改:
*** CarProduct类是汽车生产模型的示例,展示了如何通过组合不同类来构建复杂的对象结构*/
public class CarProduct {/*** 程序的入口点* 创建汽车对象及其组成部分,并初始化* @param args 命令行参数*/public static void main(String[] args) {// 创建轮胎对象,指定轮胎大小Tire tire = new Tire(20);// 创建底盘对象,包含上面创建的轮胎Bottom bottom = new Bottom(tire);// 创建车身对象,包含上面创建的底盘Framework framework = new Framework(bottom);// 创建汽车对象,包含上面创建的车身Car car = new Car(framework);// 初始化汽车对象car.init();}/*** 汽车对象*/static class Car {private Framework framework;/*** 构造方法,初始化汽车的车身* @param framework 汽车的车身*/public Car(Framework framework) {this.framework = framework;}/*** 初始化汽车对象,包括其车身*/public void init() {framework.init();}}/*** 车身Framework*/static class Framework {private Bottom bottom;/*** 构造方法,初始化车身的底盘* @param bottom 车身的底盘*/public Framework(Bottom bottom) {this.bottom = bottom;}/*** 初始化车身对象,包括其底盘*/public void init() {bottom.init();}}/*** 底盘Bottom*/static class Bottom {private Tire tire;/*** 构造方法,初始化底盘的轮胎* @param tire 底盘的轮胎*/public Bottom(Tire tire) {this.tire = tire;}/*** 初始化底盘对象,包括其轮胎*/public void init() {tire.init();}}/*** 轮胎Tire*/static class Tire {private int size;//轮胎大小/*** 构造方法,初始化轮胎的大小* @param size 轮胎的大小*/public Tire(int size) {this.size = size;}/*** 初始化轮胎对象,打印轮胎大小*/public void init() {System.out.println("轮胎大小:" + size);}}
}
我们可以看到,通过上面的修改,就算底层类发生变化,整个调用链的代码也是不用做任何修改的,这样就实现代码之间的解耦,从而提高了代码的灵活性、复用性。
我们来对比一下传统程序开发流程和控制反转程序开发流程:

我们可以看到,传统的开发流程是:Car依赖Framework,Framework依赖Bottom,...。而在改进之后的代码中,控制权发生了反转,不再是由上级对象创建下级对象并控制下级对象,而是下级对象注入到上级对象中,下级对象不再受上级对象的控制,这样就算下级对象发生改变,也不会影响到上级对象,这就是典型的控制反转,也就是IoC的实现思想。
如何理解Spring IoC
在以往的程序设计中,对象之间的依赖关系通常是由程序内部通过new关键字来实现的,这样的方式,会导致程序内部与具体实现的对象紧密联系(即耦合度高),一旦对象的实现发生改变,那么对于程序中的一部分代码也需要进行修改,这不仅增加了开发成本,而且也增加了代码的维护难度。
Spring IoC则是将对象的创建和管理权交给了Spring容器。在Spring容器中,所有的对象称为Bean,并通过配置文件或注解等方式来进行获取对象。当程序某处需要用到Bean对象时,Spring容器就会负责查找、创建、注入Bean对象。而程序本身不需要关心Bean对象时如何实例化和管理的。这种方式的创建和管理权从原先的程序中转移到Spring容器中,从而实现了控制反转(IoC)。
Spring IoC的优点
- 降低耦合度:通过把对象的实例和管理权交给Spring容器,从而让程序与对象之间的耦合性降低,使得代码更加灵活、可维护、可复用。
- 提高可扩展性:由于对象的创建和管理权交给了Spring容器,当我们需要添加新的功能或模块时,我们只需要在Spring中注册相应的bean即可。
- 简化开发:使用Spring IoC可以简化开发。开发者只需要关注业务逻辑的实现,而不需要花费过多的精力在对象的创建和管理上。
- 提高性能:虽然使用Spring IoC会增加一些额外的开销,但在大多数情况下,这种开销是微不足道的。而且,通过使用Spring IoC,可以减少不必要的对象创建和销毁,从而提高应用程序的性能。
DI(依赖注入)
DI(Dependcy Injection,即依赖注入)是一种软件设计模式,用于实现松耦合和可测试性的代码结构。在寻常的编程中,对象通常自己负责创建和管理它锁依赖的其他对象,这样导致了对象之间的耦合度高,使得对象难以复用和测试。
而DI是一种实现控制反转(Inversion of Control,简称 IoC)的机制。它允许对象之间的依赖关系由外部容器(Spring 容器)来管理,而不是由对象自身来创建或查找依赖对象。这种方式可以减少对象之间的耦合性,提高代码的可重用性和可维护性。
DI的实现方式
DI的主要实现方式包括构造函数注入、属性注入和方法注入。
- 构造函数注入是最常见的DI方式,它通过在对象的构造函数中传递依赖对象来实现。
- 属性注入是通过设置对象的属性来注入依赖对象。
- 方法注入是一种更灵活的DI方式,它通过在对象的方法中传递依赖对象来实现。
DI的优点
- 降低耦合度:DI使得对象之间的耦合度降低,因为对象不直接创建依赖,而是通过外部注入的方式获得。这使得每个对象更加独立,更易于管理和维护。
- 提高代码的可维护性:由于对象之间的耦合度降低,修改一个对象时对其他对象的影响也会减少,这使得代码更易于维护和升级。
- 提高灵活性:DI使得对象的依赖关系可以动态地管理和修改,这使得代码更加灵活,可以根据实际需求进行修改和扩展。
- 增强代码的可测试性:依赖注入使得单元测试变得更加容易。开发者可以通过注入模拟(mock)对象或存根(stub)来测试组件的行为,而不需要依赖于实际的依赖对象。
- 提高代码的可重用性:由于对象不依赖于具体的实现,而是依赖于抽象(接口或抽象类),因此可以更容易地替换对象的实现,从而提高代码的可重用性。
Spring相关网站
Spring官方网站:Spring | Homehttps://spring.io/https://spring.io/
https://spring.io/
Spring Framework官方文档:Spring Framework 文档 :: Spring Frameworkhttps://docs.spring.io/spring-framework/reference/https://docs.spring.io/spring-framework/reference/
https://docs.spring.io/spring-framework/reference/
Spring Boot官方文档:Spring Boot :: Spring Boothttps://docs.spring.io/spring-boot/index.htmlhttps://docs.spring.io/spring-boot/index.html
https://docs.spring.io/spring-boot/index.html
Spring Cloud官方文档:Spring Cloudhttps://spring.io/projects/spring-cloud#learnhttps://spring.io/projects/spring-cloud#learn
https://spring.io/projects/spring-cloud#learn
Spring源代码仓库:Spring · GitHubhttps://github.com/spring-projectshttps://github.com/spring-projects
https://github.com/spring-projects
Spring源代码仓库中文文档:Spring Framework 中文文档https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/
https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/
Spring Boot中文文档:Spring Boot 参考https://www.docs4dev.com/docs/spring-boot/2.4.6/reference/getting-started.html#getting-startedhttps://www.docs4dev.com/docs/spring-boot/2.4.6/reference/getting-started.html#getting-started
https://www.docs4dev.com/docs/spring-boot/2.4.6/reference/getting-started.html#getting-started
Spring Cloud中文文档:Spring Cloud 中文文档https://www.docs4dev.com/docs/zh/spring-cloud/Finchley.SR2/reference/https://www.docs4dev.com/docs/zh/spring-cloud/Finchley.SR2/reference/
https://www.docs4dev.com/docs/zh/spring-cloud/Finchley.SR2/reference/

以上就是本篇所有内容啦~
若有不足,欢迎指正~
相关文章:
【Spring】什么是Spring?
什么是Spring? Spring是一个开源的轻量级框架,是为了简化企业级开发而设计的。我们通常讲的Spring一般指的是Spring Framework。Spring的核心是控制反转(IoC-Inversion of Control)和面向切面编程(AOP-Aspect-Oriented Programming)。这些功能使得开发者…...
[笔记] 汇编杂记(持续更新)
文章目录 前言举例解释函数的序言函数的调用栈数据的传递 总结 前言 举例解释 // Type your code here, or load an example. int square(int num) {return num * num; }int sub(int num1, int num2) {return num1 - num2; }int add(int num1, int num2) {return num1 num2;…...
开放式TCP/IP通信
一、1200和1200之间的开放式TCP/IP通讯 第一步:组态1214CPU,勾选时钟存储器 第二步:防护与安全里面连接机制勾选允许PUT/GET访问 第三步:添加PLC 第四步:点击网络试图,选中网口,把两个PLC连接起…...
(原创,可用)SSH实现内外网安全穿透(安全不怕防火墙)
目前有A、B终端和一台服务器,A、B机器不能直接访问,服务器不能直接访问A、B终端但是A、B终端可以访问服务器,这个场景很像我们有一台电脑在单位内网,外机器想访问内网系统,可能大家目前想到的就是frp之类穿透工具&…...
第二节 docker基础之---镜像构建及挂载
查看当前镜像: [rootdocker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE [rootdocker ~]#很明显docker是咱们新搭建的所以目前还没有镜像 1,搜索镜像: [rootdocker ~]# docker search centos 搜索镜像并过滤是官…...
LLM学习笔记1——本地部署Meta-Llama-3.2-1B大模型
系列文章目录 参考博客 参考博客 文章目录 系列文章目录前言与调用一、部署要求二、实现步骤0.深度学习环境错误1,验证pytorch版本时提示以下问题:错误2,验证pytorch版本时提示以下问题:错误3,有时候还会提示你有一些…...
RNN-day1-NLP基础
NLP基础 一、基本概念 自然语言处理:Natural Language Processing,主要目标是让计算机能够理解、解释和生成人类语言的数据。 1 基本概念 1.1NLP概念 语言:人类沟通的机构化系统,包括声音、书写符号、手势 自然语言:自然进化…...
常见string库中的函数(C语言超详细)
文章目录 strcspnstrcpystrncpystrcatstrncatstrcmpstrncmpstrchrstrrchrstrstrstrtokstrlenstrnlen strcspn 原型: size_t strcspn(const char *str1, const char *str2);功能: strcspn 会扫描 str1,并返回一个整数,表示 str1 中第一个匹配…...
AI安全最佳实践:AI应用开发安全评估矩阵(上)
生成式AI开发安全范围矩阵简介 生成式AI目前可以说是当下最热门的技术,吸引各大全球企业的关注,并在全球各行各业中带来浪潮般的编个。随时AI能力的飞跃,大语言模型LLM参数达到千亿级别,它和Transformer神经网络共同驱动了我们工…...
deepseek+kimi自动生成ppt
打开deepseek官网,输入详细的需求,让他生成个ppt 接着deepseek开始思考生成了 接着复制生成了的内容 打开kimi粘贴刚才deepseek生成的内容 可以一键生成啦,下载编辑使用吧...
# C指针地址CUP寄存器访问IO内存映射
C指针地址&CUP寄存器访问&IO内存映射 在裸机编程中,C语言可以像汇编语言一样直接操作芯片寄存器地址进行读取和写入,主要是由于以下几个原因: 1. 裸机环境下没有操作系统的干预 裸机编程是指直接在硬件上运行程序,没有…...
《薄世宁医学通识50讲》以医学通识为主题,涵盖了医学的多个方面,包括医学哲学、疾病认知、治疗过程、医患关系、公共卫生等
《薄世宁医学通识50讲》是一门由薄世宁医生主讲的医学通识课程,该课程旨在通过深入浅出的方式,向广大听众普及医学知识,提升公众对医学的认知和理解。 晓北斗推荐-薄世宁医学通识 以下是对该课程的详细介绍: 一、课程概述 《薄世…...
突破与重塑:逃离Java舒适区,借Go语言复刻Redis的自我突破和成长
文章目录 写在文章开头为什么想尝试用go复刻redis复刻redis的心路历程程序员对于舒适区的一点看法关于mini-redis的一些展望结语 写在文章开头 在程序员的技术生涯长河中,我们常常会在熟悉的领域中建立起自己的“舒适区”。于我而言,Java 就是这片承载…...
解决_ssl.so: cannot open shared object file: No such file or directory
背景: 我在CentOS8.2的操作系统里安装完python2.7后,源码安装了OpenSSL_1_1_1-stable 下载地址: https://github.com/openssl/openssl/tree/OpenSSL_1_1_1-stable 现象: 结果python导入ssl的时候报错了,报找不到_ssl.…...
优惠券平台(一):基于责任链模式创建优惠券模板
前景概要 系统的主要实现是优惠券的相关业务,所以对于用户管理的实现我们简单用拦截器在触发接口前创建一个单一用户。 // 用户属于非核心功能,这里先通过模拟的形式代替。后续如果需要后管展示,会重构该代码 UserInfoDTO userInfoDTO new…...
【Pytorch实战教程】PyTorch中的Dataset用法详解
PyTorch中的Dataset用法详解 在深度学习中,数据是模型训练的基石。PyTorch作为一个强大的深度学习框架,提供了丰富的工具来处理和加载数据。其中,Dataset类是PyTorch中用于处理数据的重要工具之一。本文将详细介绍Dataset的用法,帮助你更好地理解和使用它。 1. 什么是Dat…...
单例设计模式(Java)
(部分内容参考于菜鸟教程当中关于单例模式的说明) 什么是单例设计模式? 单例模式(Singleton Pattern)是一种常见的设计模式,其主要目的是确保一个类在系统中只有一个实例,并提供全局访问点。使…...
TensorFlow域对抗训练DANN神经网络分析MNIST与Blobs数据集梯度反转层提升目标域适应能力可视化...
全文链接:https://tecdat.cn/?p39656 本文围绕基于TensorFlow实现的神经网络对抗训练域适应方法展开研究。详细介绍了梯度反转层的原理与实现,通过MNIST和Blobs等数据集进行实验,对比了不同训练方式(仅源域训练、域对抗训练等&am…...
09vue3实战-----引入element-plus组件库中的图标
09vue3实战-----引入element-plus组件库中的图标 1.安装2.引入3.优化 element-plus中的icon图标组件的使用和其他平台组件(如el-button按钮)是不一样的。 1.安装 npm install element-plus/icons-vue2.引入 在这我们只讲述最方便的一种引入方法------完整引入。这需要从elem…...
DeepSeek vs. ChatGPT:不同的诞生时间,对人工智能发展的不同影响
DeepSeek vs. ChatGPT:不同的诞生时间,对人工智能发展的不同影响 ChatGPT 和 DeepSeek 诞生于不同的时间节点,代表了人工智能不同阶段的发展方向。它们在技术、应用以及对AI发展趋势的影响方面各有侧重。 1. 诞生时间与背景 ChatGPT&#x…...
如何导入第三方sdk | 引入第三方jar 包
0. 背景1. 上传私有仓库2. 使用本地文件系统 0. 背景 对接一些第三方功能,会拿到第三方的sdk,也就是jar包,如何导入呢 1. 上传私有仓库 最好的方式就是将第三方jar包,上传到私有的仓库,这样直接正常在pom引用即可如果只…...
消费电子产品中的噪声对TPS54202的影响
本文章是笔者整理的备忘笔记。希望在帮助自己温习避免遗忘的同时,也能帮助其他需要参考的朋友。如有谬误,欢迎大家进行指正。 一、概述 在白色家电领域,降压转换器的应用非常广泛,为了实现不同的功能就需要不同的电源轨。TPS542…...
[Meet DeepSeek] 如何顺畅使用DeepSeek?告别【服务器繁忙,请稍后再试。】
文章目录 [Meet DeepSeek] 如何顺畅使用DeepSeek?告别【服务器繁忙,请稍后再试。】引言使用渠道一:硅基流动 Chatbox AI【推荐】硅基流动 Chatbox AI的优势 使用渠道二:秘塔AI搜索秘塔AI搜索的优势 其它方案1. DeepSeek官网2. 纳…...
Websocket从原理到实战
引言 WebSocket 是一种在单个 TCP 连接上进行全双工通信的网络协议,它使得客户端和服务器之间能够进行实时、双向的通信,既然是通信协议一定要从发展历史到协议内容到应用场景最后到实战全方位了解 发展历史 WebSocket 最初是为了解决 HTTP 协议在实时…...
学习Cherry Studio AI服务平台,主要是各种功能的实践(deepseek 1.5b和7b的模型+ChatGLM3模型)
Cherry Studio 介绍 Cherry Studio 是一个支持多模型服务的桌面客户端,为专业用户而打造,内置 30 多个行业的智能助手,帮助用户在多种场景下提升工作效率。 CherryStudio内置众多服务商 同时也支持其他兼容OpenAI/Anthropic等API格式的服务…...
【实用教程】在 Android Studio 中连接 MuMu 模拟器
MuMu 模拟器是一个非常流行的安卓模拟器,特别适合开发人员进行应用测试,我使用它的根本原因在于Android Studio自带的AVM实现是太难用了,但是Mumu模拟器启动以后不会自动被Android Studio识别到,但是其他模拟器都是能够正常被Andr…...
Linux 系统搭建 Python 开发环境全流程
Linux 系统搭建 Python 开发环境全流程 Python 解释器下载 Pycharm 对应版本解压安装包进入解压后的目录启动 Pycharm创建桌面快捷方式(可选)Pycharm 配置创建第一个目录第一个程序运行补充 Python 解释器 确保电脑里已经有了python解释器,没…...
VUE小技能:通过 Prop 向子组件传递数据
文章目录 引言Props 声明Prop 校验更改 prop引言 一个组件需要显式声明它所接受的 props,这样 Vue 才能知道外部传入的哪些是 props,哪些是透传 attribute。所有 prop 默认都是可选的,除非声明了 required: true。Props 声明 在使用 <script setup> 的单文件组件中,p…...
第16章 Single Thread Execution设计模式(Java高并发编程详解:多线程与系统设计)
简单来说, Single Thread Execution就是采用排他式的操作保证在同一时刻只能有一个线程访问共享资源。 1.机场过安检 1.1非线程安全 先模拟一个非线程安全的安检口类,旅客(线程)分别手持登机牌和身份证接受工作人员的检查,示例代码如所示。…...
AtCoder Beginner Contest 392(A-G)题解
A-B:略 C:可能题意比较绕,第i个答案就是穿着i这个号码(也就是Q[j] i,这个时候j这个位置),看向的那个人的号码(也就是P[j]) 代码: void solve() {int n;cin >> n;vi p(n 1…...
