Spring IoCDI(上)--初识

news2024/11/24 5:00:25

1. IoC & DI ⼊⻔

1.1 Spring 是什么

        通过前⾯的学习, 我们知道了Spring是⼀个开源框架, 他让我们的开发更加简单. 他⽀持⼴泛的应⽤场 景, 有着活跃⽽庞⼤的社区, 我们⽤⼀句更具体的话来概括Spring, 那就是: Spring 是包含了众多⼯具⽅法的 IoC 容器

1.1.1 什么是容器

        所谓容器,是⽤来容纳某种物品的装置,我们之前学到的数据结构中 List/Map -> 数据存储容器 ; 服务器开发中Tomcat -> Web 容器;

1.1.2 什么是 IoC 容器

        IoC是Spring的核心思想。

        其实IoC在前面的代码练习已经使用过了,比如在类上面添加 @RestController 和 @Controller 注解,就是把这个对象交给Spring管理,Spring框架启动时,就会加载该类。

        故此,把对象交给Spring管理,这就是IoC思想。

        IoC:Inversion of Control(控制反转),也就是说Spring是一个“控制反转”的容器。

        所谓控制反转,就是控制权反转,也就是程序获得依赖对象的过程被反转了;

        简单来说就是当需要某个对象时,把创建对象的任务交给容器,程序中只需要依赖注入(Dependency Injection,简称DI)就可以了。这个容器称为:IoC容器。Spring是一个IoC容器,所以有时也称为Spring容器。(传统开发模式需要自己通过 new 创建对象,现在不需要再进行创建了,引入了Ioc思想之后,我们就不需要自己进行创建对象了)

2. IoC介绍

        下面通过案例来介绍什么是IoC,现在需求:造一辆车;

2.1 传统程序开发

        我们是实现思路是这样的:先设计轮子(Tire),然后根据轮子的大小设计底盘(;),接着根据底盘设计车身(FrameWork),最后根据车身设计好整个汽车(Car)。这里就出现了一个 “依赖” 关系:汽车依赖车身,车身依赖底盘,底盘依赖轮子。如图:

 代码如下:

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.run();
    }
}
 
public class Car {
    private FrameWork frameWork;
    public Car() {
        frameWork = new FrameWork(17);
        System.out.println("frameWork init....");
    }
    public void run() {
        System.out.println("Car run...");
    }
}
 
public class FrameWork {
    private Bottom bottom;
    public FrameWork(int size) {
        bottom = new Bottom(size);
        System.out.println("Bottom init...");
    }
}
 
 
public class Bottom {
    private Tire tire;
    public Bottom(int size) {
        tire = new Tire(size);
        System.out.println("Tire init....");
    }
}
 
public class Tire {
    private int size;
    public Tire(int size) {
        this.size = size;
    }
}

        运行结果如下:

        如果有新的需求了,要修改轮胎的颜色,那就要多添加一个属性,那么传参的时候,Car类、FrameWork类、Bottom类、Tire类的构造函数都要多添加一个元素,传参也要多传一个颜色属性。这样的话,耦合就很高了;而这也只是简单的给轮胎添加一个属性,随着项目需求的增加,项目也会越来越复杂,现在的代码可维护性也很差,就不太合适了。所以,要进行改进。

2.2 解决方案

        上面的程序中,我们是根据轮胎的尺寸设计底盘的,轮胎的尺寸已改,底盘的设计也就得改,而车身依赖底盘,就会导致一连串的问题,几乎整个设计都得改。

        现在换一种思路,我们先设计汽车的大概样子,然后根据汽车的样子来设计车身,根据车身来设计底盘,最后根据底盘设计轮胎。这时候,依赖关系就反转过来了:轮胎依赖底盘,底盘依赖车身,车身依赖汽车。

        这就类似于我们造一辆完整的汽车,如果所有的配件都是自己造,那么客户需求发生改变的时候,比如轮胎尺寸不再是原来的尺寸了,那我们就要自己手动来改了,但如果把轮胎外包出去,那么即使轮胎的尺寸发生改变,那么我们只需要向代理工厂下订单就行了,我们自身是不需要出力的。

  

         关于如何实现这种设计开发思想,我们可以尝试不在每个类中创建下级类,如果自己创建下级类就会出现当下级类发生改变操作,自己也要跟着修改此时我们只需要将原来有自己创建的下级类,改为注入的方式,因为我们不需要在当前类中创建下级类了,所以下级类即使发生变化(创建或减少参数),当前类本身也无需修改任何代码,这样就完成了程序的解耦

2.3 IoC程序开发

        我们根据新的设计开发思想把调用汽车的程序改造一下,把创建子类的方式,改为注入传递的方式。具体代码如下:

public class Main {
    public static void main(String[] args) {
        Tire tire = new Tire(17);
        Bottom bottom = new Bottom(tire);
        FrameWork frameWork = new FrameWork(bottom);
        Car car = new Car(frameWork);
        car.run();
    }
}
 
public class Car {
    private FrameWork frameWork;
    public Car(FrameWork frameWork) {
        this.frameWork = frameWork;
        System.out.println("frameWork init....");
    }
    public void run() {
        System.out.println("Car run...");
    }
}
 
public class FrameWork {
    private Bottom bottom;
    public FrameWork(Bottom bottom) {
        this.bottom = bottom;
        System.out.println("Bottom init...");
    }
}
 
public class Bottom {
    private Tire tire;
    public Bottom(Tire tire) {
        this.tire = tire;
        System.out.println("Tire init....");
    }
}
 
public class Tire {
    private int size;
    public Tire(int size) {
        this.size = size;
        System.out.println("size:" + size);
    }
}

         如此,如果轮胎需要修改尺寸,或者添加一个属性,只需要修改Tire类就好了,其他类不需要修改,即达到了解耦的效果。

2.4 IoC优势

        在传统代码中的对象创建顺序是:Car -> Framework -> Bottom -> Tire

        改进之后解耦的代码的对象创建顺序是:Tire -> Bottom -> Framework -> Car,如下图所示:

        

         我们发现,程序的实现代码顺序和类的创建顺序是反的,传统代码是Car控制并创建了Framework,Framework的创建也会继续创建Bottom,依次往下递推,而改进后的控制权发生了反转,不再是使用方创建对象并控制依赖对象了,而是把依赖对象注入到当前对象中,依赖对象的控制权不再由当前类控制。这样的话,即使依赖类发生任何改变,当前类都是不受影响的,这就是典型的控制反转,也是IoC的实现思想。

        而控制反转容器也就是IoC容器,如图:

        上面容器中的代码就是IoC容器做的工作。

        由此可以看出,IoC具有以下优点:资源不由使用资源的双方管理,而由使用资源的第三方管理,这可以带来很多好处。

        第一,资源集中管理,实现资源的可配置和易管理。

        第二,降低使用资源双方的依赖程度,也就是我们说的耦合度。

        资源集中管理:IoC容器会帮我们管理一些资源(对象等),我们需要使用时,只需要从IoC容器中去取就可以了。

        解耦合:我们在创建实例的时候不需要了解其中的细节,降低了使用资源双方的依赖程度,也就是耦合度。

        而Spring就是一种IoC容器,帮助我们来做了这些资源管理。

 3. DI介绍

        DI:Dependency Injection(依赖注入);容器在运行期间,动态的为应用程序提供运行时所依赖的资源,称为依赖注入。

        程序运行时,需要某个资源,此时容器就为其提供这个资源。从这点来看,依赖注入(DI)和 控制反转(IoC)是从不同的角度描述同一件事,就是指通过引入IoC容器,利用依赖关系注入的方式,实现对象之间的解耦。

        上面改进后的代码,就是通过构造函数,把依赖对象注入到需要使用的对象中。如图:

          IoC是一种思想,也是 “目标”,而思想只是一种指导原则,最终还是要有可行的落地方案,而DI就属于具体的实现。所以也可以说,DI是IoC的一种实现。 

ps:本次的内容就到这里了,如果对你有所帮助的话,就请一键三连哦!!!

本文的封面来自:bilibili苏杉杉的pv,侵权删 url:https://www.bilibili.com/video/BV1vo4y167eh/?spm_id_from=333.999.0.0&vd_source=866da5be2ef0ddd213b053523da53138
————————————————

电子签名:上嘉路

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

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

相关文章

C#委托(入门)

1、语法 步骤 ①定义一个委托类型, 如Help ②委托类型实例化为委托实例 ③定义函数(与委托类型相匹配的) ④将函数交给委托实例使用 示例一 //方法一 void MyFunc1() {Console.WriteLine("Hello"); }//方法二 void MyFunc2() {Console.WriteLine("World&…

STM32总线和时钟树(速记版)

一、存储器结构 1.1 STM32内存结构 型号说明 以STM32F103RBT6这个型号的芯片为例,该型号的组成为7个部分,其命名规则如下: ST 是公司名,意法半导体。M 代表Cortex-M内核。32 代表32位微控制器。 F103 是芯片系列。 R 代表引脚数…

算法基础知识——11种距离度量

简介:个人学习分享,如有错误,欢迎批评指正。 前言:距离的作用 数据聚类:距离度量在聚类算法(如K-means、层次聚类)中用于衡量数据点之间的相似性或差异性,帮助确定聚类的中心和边界…

10款开源管理工具大比拼:哪个最适合您的团队?

国内外主流的 10 款开源项目管理系统对比:PingCode、Worktile、Gitee、开源中国 (OSChina)、禅道 (ZenTao)、OpenProject、Redmine、Leantime、MeisterTask、Freedcamp。 在选择合适的开源项目管理工具时,你是否感到困惑和不安?市场上众多的选…

Python | Leetcode Python题解之第338题比特位计数

题目: 题解: class Solution:def countBits(self, n: int) -> List[int]:bits [0]for i in range(1, n 1):bits.append(bits[i & (i - 1)] 1)return bits

SSTI模版注入(初步)

SSTI模版注入(初步) ssti可能造成任意文件读取和RCE远程控制后台系统 漏洞成因:渲染模版时,没有严格控制对用户的输入; 使用了危险的模版,导致用户可以混合flask程序进行交互。 flask是基于python开发的…

【C++高阶】哈希—— 位图 | 布隆过滤器 | 哈希切分

✨ 人生如梦,朝露夕花,宛若泡影 🌏 📃个人主页:island1314 🔥个人专栏:C学习 ⛺️ 欢迎关注:👍点赞 👂&am…

Ubuntu系统安装CH340驱动

今天在使用USB转UART模块连接设备时发现我的Ubuntu虚拟机无法识别USB设备,这个模块使用的CH340芯片,在Windows主机中可以识别到串口并连接,所以初步判断为虚拟机中缺少ch340驱动。实际上自Linux内核版本2.6.24起,Linux主线内核已内…

云原生-Docker安全-容器逃逸系统内核漏洞(解决docker.com无法访问)

云原生-Docker安全-容器逃逸&系统内核漏洞 细节部分在权限提升章节会详解,常用: CVE-2016-5195 CVE-2019-16884 CVE-2021-3493 CVE-2021-22555 CVE-2022-0492 CVE-2022-0847 CVE-2022-23222 云原生-Docker安全-容器逃逸&docker版本漏洞 CVE…

基于Java的医院急诊系统

TOC springboot327基于Java的医院急诊系统 第1章 绪论 1.1选题动因 当前的网络技术,软件技术等都具备成熟的理论基础,市场上也出现各种技术开发的软件,这些软件都被用于各个领域,包括生活和工作的领域。随着电脑和笔记本的广泛…

【中等】 猿人学web第一届 第7题 动态字体,随风漂移

文章目录 获取字体文件映射关系获取页面英雄排序python 代码 这道题是 动态字体文件加密,找出动态字体文件中对应数字相同规律即可 数据接口 https://match.yuanrenxue.cn/api/match/7 数据接口没有加密值 cookie字段也没有 获取字体文件映射关系 多次观察 字体文件…

2.2 Oracle与SQL Server简介

欢迎来到我的博客,很高兴能够在这里和您见面!欢迎订阅相关专栏: 工💗重💗hao💗:野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典:收集整理全网各大IT互联网公司技术、项目、HR面试真题.…

仿Muduo库实现高并发服务器——事件监控Poller模块

Poller模块在整个项目的使用 下面代码是对I/O复用接口函数的基本使用。 回顾上篇文章:事件监控管理模块 这个模块是将触发事件的描述符,给到外面,让外面去做对应的处理。 #define MAX_EPOLLEVENTS 1024 class Poller {private:int _epfd;s…

三级_网络技术_18_路由器的配置及使用

1.在Cisco路由器上用于永久保存路由器的开机诊断程序、引导程序和操作系统软件的存储器是()。 Flash NVRAM RAM ROM 2.在Cisco路由器中主要用来永久保存路由器的开机诊断程序、引导程序和操作系统,以完成路由器初始化进程的存储器是()。 RAM Disk Flash RO…

Linux平台使用OPUS对Audio PCM数据进行编解码

1)Audio编解码入门级小知识,分享给将要学习或者正在学习Audio编解码开发的同学。 2)内容属于原创,若转载,请说明出处。 3)提供相关问题有偿答疑和支持。 Opus编码是一个开源的音频编码格式,具…

ArduPilot二次开发零基础教程

文章目录 前言一、概述二、开发环境搭建三、多旋翼MAVROS自主控制接口四、无人船(车)MAVROS自主控制接口五、二次开发基础六、控制LED灯七、自定义串口驱动八、Guided控制接口九、输出自定义PWM信号十、添加自定义MAVLINK消息和QGC通信十一、自定义日志十…

[MRCTF2020]套娃1

打开题目,查看源代码,有提示 有两层过滤 1.过滤"_"与"%5f" 。 这里要求的参数必须是"b_u_p_t"但是不能检测出"_"。这里看着很作弄人。其实这里要用到php里非法参数名的问题。可以参考一下博客 ?b.u.p.t2333…

探索Pandas的魔力:Python数据分析的终极武器

文章目录 探索Pandas的魔力:Python数据分析的终极武器背景:为何选择Pandas?引言:Pandas是什么?安装Pandas:一键安装的便捷基础函数:Pandas的五大法宝应用场景:Pandas的实战演练常见问…

浏览器调试工具-Chrome Dev Tools

浏览器调试模式下的各个调试工具是常用的工具集,能够帮助开发者理解、调试和优化网页。 1.打开方式 直接在浏览器中按下F12键右键点击页面上的任一元素,选择“检查”(Inspect)在浏览器右上角点击菜单按钮,选择“更多…

Redis:缓存击穿,缓存穿透,缓存雪崩

缓存穿透 缓存和数据库中都没有的数据,可用户还是源源不断的发起请求,导致每次请求都会到数据库,从而压垮数据库。 这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。 *** 解决方案** 对空值进行缓存标…