什么是Spring,Spring的核心和设计思想你了解吗?

news2024/12/29 8:33:50

目录

1.初识Spring 

1.1 什么是容器

1.2 什么是IoC

2.什么是IoC容器.

2.1 什么是DI


哈喽呀,你好呀,欢迎呀,快来看一下这篇宝藏博客吧~~~


1.初识Spring 

Srping指的是Spring Framework(Spring 框架).我们经常会听见框架二字,其中java中最最主流的框架当属Spring.Spring是一个开源框架,有着活跃且庞大的社区.那说了这么多,Spring框架又是什么呢,又有什么作用呢?

再具体一点来说,Spring框架就是一个包含了众多工具方法的IoC容器.基于这个容器,Java企业级的开发可以变得更简单.那么问题又来了,IoC容器又是什么呢?

1.1 什么是容器

了解IoC容器之前,我们得先了解一下什么是容器.在java中,应该了解List/Map吧,List/Map就是一个数据存储的容器.还有Tomcat,它就是一个web容器.所以啊,容器啊,其实就和它字面上的意思差不多,就是用来容纳某种物品的装置,可放可取.List/Map存放的是一些数据,有些网站就是运行在tomcat这个容器上.那IoC容器具体是干嘛的呢?

1.2 什么是IoC

IoC全称Inversion of Control,翻译成中文就是"控制反转"的意思.也就是说Spring是一个"控制反转"的容器.怎么理解这个"控制反转"呢,我们先来看一个例子:

比如我现在要造一辆车:

第一种思想就是造车需要依赖车身,车身需要依赖底盘,底盘需要依赖轮胎.大致流程如下图:

代码实现:

public class NewCar {
    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 = 20;
        public void init() {
            System.out.println("轮胎尺⼨:" + size);
        }
    }
}

按照上诉思想,我们确实是可以实现一辆车的构造的.但是仔细想一下,我现在的车的轮胎尺寸是固定的,随着用户需求的增大,轮胎的尺寸需求可能不一样,这时,我们就需要改变一下代码了:

public class NewCar2 {
    public static void main(String[] args) {
        Car car = new Car(20);
        car.run();
    }
    /**
     * 汽⻋对象
     */
    static class Car {
        private Framework framework;
        public Car(int size) {
            framework = new Framework(size);
        }
        public void run() {
            // 依赖⻋身
            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);
        }
    }
}

对比一下这两段代码,我们可以发现,就新增轮胎尺寸这一小改动,这个车的整个链就都要发生改动.

以上仅仅只是改动了轮胎的尺寸,但是随着用户需求的多样化,比如对轮胎的材质,样式等等可能会有各种各样的要求,每一个小的改动都会触发整个链,显然,这就加大了成本.那有没有另外一种思想,当我们修改底层代码时,不会影响到其他的业务代码呢?要找到另一种更好的方法,我们就要分析一下,为什么当前代码不太好.通过观察我们可以发现,一环扣一环是因为每一个类中都new了自己依赖的一个下级类,当下级类改变时,上级类就需要做出相应的更改.故这样的设计就会导致下级出现问题,上级就要进行修改.

所以为了降低它这个耦合度,我们就可以用以下这个方法:

我们不再在类中new一个它所依赖的下级类了,而是将下级类主动的传进去(也就是注入),按照这种方法,我们就不需要将new它的下级类,这样下级类改不改变都不会影响我当前类的设计.就成功完成了解耦.

按照以上的思路,我们将创建下级对象改为注入传递下级对象的方式,代码如下:

public class NewCar3 {
    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.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

从这张图片我们就可以看出,这两种设计方法对类的创建恰恰是相反的.第一种思想是:先创建汽车类,再由汽车类创建并控制车身类,然后车身类创建并控制底盘类,依次向下,直到底层.也就是说,由当前类创建并控制下级类的,依次向下,直到底层,环环相扣.而第二种思想是与第一种截然不同的是,将这种从上到下的控制权进行了反转.也就是说,下级类不再由当前类所创建了,而是下级类自己主动注入到当前类中.这样下级类就摆脱了当前类的控制,故下级类无论怎样变,都不会影响到当前类了,这就是典型的控制反转,也就是IoC的实现思想.

2.什么是IoC容器.

还是回到我们最开始的这句话上:Spring是一个包含了众多工具的IoC(控制反转)容器.至于这个"众多工具"我以后再讲,现在可以粗略的理解为具有很多功能.控制反转相信大家通过上述造车的例子已经有所了解了,就是通过注入"属性"的方法.将控制权反转.

Spring是一个包含了众多工具的IoC容器,这句话归根结底,就还是"容器"二字.既然是"容器",那它就具备两个最基本的功能:

  1. 将对象存入容器
  2. 从容器中取出对象

所以我们要学习Spring最核心的功能就是,就是如何将对象存储到容器中,再从Spring中将对象取出来.

IoC容器和普通程序开发的区别:

将对象存储到IoC容器中就相当于我们在做一项工程时,将需要的工具都先存放在仓库里面.需要的时候直接取就行了,用完了再放回去.而之前new 对象的方式就相当于需要的时候就现做,用完了就销毁,某个时候又需要的话就再重新创建.这就是IoC容器和普通程序开发的区别.从中我们也可以发现IoC的优势之处.

Spring是一个IoC容器,说的是对象的创建和销毁都交给Spring来控制了.它本身又具有存储对象和获取对象的权利.

2.1 什么是DI

说到IoC就不得不提到DI(Dependency Injection),翻译成中文就是"依赖注入"的意思.

依赖注入:就是在IoC运行期间,动态的将某种依赖关系注入到组件之中,它是Spring框架核心IoC技术的具体实现.DI和IoC技术是从不同角度去描述同一件事.就是指通过引入IoC容器,利用依赖注入的方式,实现对象之间的解耦.

IoC是一种思想,可以理解为一种指导原则,但是最终还需要有可行的方案.而DI就是这个方案的具体实现.

比如我现在想减肥,那个"减肥"就是一种思想(是IoC),而我最后是通过跑步还是跳绳来减减肥呢?这就是具体的而实现,就是DI.

好啦,看到这里就结束啦,考考你,以下问题都会了吗:

  • Spring是什么?如何理解Spring?
  • IoC和DI是什么?有什么区别?
  • Spring最核心的功能时还是啥呢?

如果答不上来,就再看一下这篇博客吧~~

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

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

相关文章

SAP S4 FI后台详细配置教程- PART4 (科目及税费相关配置篇)

目录 1、总帐科目 1.1编辑科目表清单 1.2 科目表分配给公司代码 1.3 定义科目组 1.4 定义留存收益科目 2、销售/购置税 2.1 维护销售/购置税务代码税率 2.2 配置销项/销项税会计科目 大家好本篇是:SAP S4 FI后台详细配置教程- PART4 (科目及税…

Fiddler的安装和使用

文章目录1、Fiddler的安装2、Fiddler的使用3、抓包工具的原理1、Fiddler的安装 官网链接:https://www.telerik.com/fiddler 进入官网首页 页面跳转后 2、Fiddler的使用 下载好后直接安装,安装后打开,它就会自动抓取HTTP包,在左…

[附源码]SSM计算机毕业设计-东湖社区志愿者管理平台JAVA

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

力扣113题引发的关于DFS和回溯的一点思考

最近刚学回溯和DFS&#xff0c;刷力扣遇到一道题&#xff08;113题&#xff09;&#xff0c;如下&#xff1a; 我们不细究回溯和DFS的区别联系。关于这道题的2种写法&#xff0c;我把第一种称为回溯。 class Solution {List<List<Integer>> res new LinkedList&l…

29.Nacos的简介与安装(springcloud)

1.Nacos 简介官网&#xff1a; https://nacos.io/zh-cn/Nacos 致力于发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集&#xff0c;帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。 Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是…

【Android Studio Gradle】发布aar到私有Artifactory仓库

1. 前言 在【Android Studio Gradle】使用Artifactory构建本地仓库中介绍了如何利用工具配置一个maven私有库&#xff0c;那么在开发library的时候为了方便难免会用到需要将该库发布到这个仓库的功能。经过测试和配置&#xff0c;确实在Artifactory仓库中也可以通过gradlew命令…

【MySQL基础】为什么大部分人选择使用MySQL数据库?

目录 一、为什么大部分人选择使用MySQL数据库&#xff1f; 二、MySQL简介 1.MySQL介绍 2.MySQL的特点 3. MySQL的版本 从用户的角度&#xff0c;针对不同的用户 从单纯的版本数字区分 &#x1f49f; 创作不易&#xff0c;不妨点赞&#x1f49a;评论❤️收藏&#x1f49…

我把皮小浪の的 蓝色妖姬系列做进了java窗口

— &#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏 unity实战入门 ⭐效果图如下 ⭐⭐涉及的相关类的包含关系图 ⭐# 视频入口&#xff1a;请点击 文章目录一…

比 O(nlog(n)) 做得更好——2.改变问题以及排序和填充数组

改变问题&#xff0c;以及对键进行排序和填充数组。 目录 【第1篇】比 O(nlog(n)) 做得更好——1.创造合适的条件 长按关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 扫码关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 …

【Redis-04】Redis两种持久化方式

Redis是基于内存的数据结构服务器&#xff0c;保存了大量的键值对数据&#xff0c;所以持久化到磁盘是非常必要的&#xff0c;Redis提供了两种持久化的方式&#xff0c;分别是RDB和AOF。下面我们看下这两种持久化方式的具体实现原理。 1.RDB持久化 首先&#xff0c;RDB持久化方…

【Spring(二)】java对象属性的配置(Bean的配置)

有关Spring的所有文章都收录于我的专栏&#xff1a;&#x1f449;Spring&#x1f448; 目录 一、前言 二、通过Setter方法配置Bean 三、通过构造器配置Bean   1. 通过属性名配置   2. 通过索引配置   3. 通过属性类型配置 四、通过p命名空间配置bean 五、引用/注入其他bean…

openEuler快速入门-openEuler系统安装openGauss数据库安装

文章目录前言一、安装openEuler系统安装二、运行虚拟机&#xff0c;配置三、安装openGauss数据库总结前言 openEuler&#xff1a;openEuler 是一款开源操作系统。当前 openEuler 内核源于 Linux&#xff0c;支持鲲鹏及其它多种处理器&#xff0c;能够充分释放计算芯片的潜能&a…

[附源码]java毕业设计网络身份认证技术及方法

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

_001_Zotero入门

Zetoro大纲一、安装Zotero二、收集题录2.1 浏览器插件2.2 通过标识符添加2.3 拖拽文献2.4 从剪切板导入2.5 批量导入2.6 手动添加&#xff08;不建议使用&#xff09;2.7 方法总结三、管理题录3.1 移动分类3.2 查重3.3 关联3.4 标签3.5 笔记3.6 RSS订阅3.7 快捷键3.8 总结四、在…

Verilog 时序逻辑 UDP

时序逻辑 UDP 与组合逻辑 UDP 在定义形式和行为功能上均有不同&#xff0c;主要区别如下&#xff1a; 1、时序逻辑 UDP 的输出端必须声明为 reg 型。2、时序逻辑 UDP 可以用 initial 语句初始化。3、状态表格式也稍有不同&#xff1a; ... : <current_state> : &l…

RabbitMQ初步到精通-第七章-RabbitMQ之延迟队列

目录 第七章-RabbitMQ之延迟队列 1. 延迟队列概念 2. 应用场景 3. 架构模式 3.1 队列TTL实现 3.2 消息TTL实现 3.3 插件实现 4. 代码验证 5. 总结 第七章-RabbitMQ之延迟队列 1. 延迟队列概念 延迟-意即 非实时&#xff0c;之前我们讨论大部分的案例都是生产者将消息发…

【毕业设计】61-基于单片机的超声波测距仪设计(原理图、仿真工程、低重复率参考设计文档、PPT、开题报告、任务书)

【毕业设计】61-基于单片机的超声波测距仪设计&#xff08;原理图、仿真工程、低重复率参考设计文档、PPT、开题报告、任务书&#xff09;[toc] 资料下载链接 资料下载链接 资料链接&#xff1a;https://www.cirmall.com/circuit/33762/ 包含此题目毕业设计全套资料&#xff…

UDS应用场景

诊断协议那些事儿 本文为诊断协议那些事儿专栏文章&#xff0c;旨在介绍诊断的应用场景&#xff0c;其本质就是一个用于汽车行业通信的需求规范&#xff0c;用于诊断功能数据的解析&#xff01;让读者对诊断有一个深入的认识。 关联文章&#xff1a;UDS协议发展历史 文章目录…

idea如何设置代理实现管理突破呢

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…

抗锯齿渲染

&#xff08;逻辑绘图&#xff09;图像在坐标图中的显示&#xff1a; 笔的默认宽度为1&#xff0c;当笔的宽度大于1时&#xff0c;相当于在则条线的两边均匀加厚&#xff0c;确定坐标的还是这条宽度为1的线段&#xff0c;相当于宽度的中心位置。 物理绘图 &#xff08;默认情况…