【Spring】学习Spring需要掌握的核心设计思想

目录

一、Spring是什么

二、什么是IoC容器

1、什么是容器

2、什么是IoC 

 3、Spring IoC

4、DI(依赖注入)

4.1、IoC和DI的区别

5、 DL(依赖查找)


一、Spring是什么

我们通常所说的Spring指的是Spring Framework(Framework的意思就是框架),它是一个开源的框架,有着庞大的社区,这就是它之所以能长久不衰的原因,Spring支持广泛的应用场景,它可以方Java企业级的应用程序开发起来更简单。

用一句话来概述Spring:Spring是包含了众多工具方法的IoC容器。

二、什么是IoC容器

1、什么是容器

容器是用来容纳某种物品的装置。 ——来自:百度百科

我们之前了解的List和Map,他们都是用来装数据的容器,这写容器把我们需要常用到的方法都已经封装好了,我们只需要知道如何使用并且知道使用什么方法可以达到我们想要实现的效果即可。还有Tomcat是一个Web容器。同理Spring就是一个IoC容器。

2、什么是IoC 

IoC是Inversion of Control的缩写,直译的意思是"控制翻转"的意思,这是一种思想,实际上IoC表示的意思为"控制权翻转"。之前我们写的代码中对象的生命周期,是由程序员或者当前的代码片段控制的;而控制权翻转就是程序中对象的生命周期不在又程序员或者当前的代码片段控制,而是由Spring(IoC容器)来控制。

下面我们通过一个例子来了解这个IoC容器

1️⃣传统代码的写法

我们都知道构造一个汽车,首先这个车需要依赖于车身(FrameWork),而车身需要依赖于底盘(Bottom),而底盘需要依赖于轮胎(Tire),这就需要我们在写代码的时候在底盘的类中new一个轮胎的对象,在车身的类中new一个底盘的对象,在车的类中需要new一个车身的对象。

 我们的车肯定有不同的款式,当我们对车的组成所依赖的对象中的属性做出指定(个性化需求)的时候,一个类添加属性的时候,其他依赖(new)这个类的类,在new对象的时候都需要进行修改。

package old;
//汽车类
public class Car {
    private Framework framework;
    public Car(){
        framework = new Framework();
    }
    public void init(){
        //依赖车身
        System.out.println("构造汽车");
        framework.init();
    }
}

package old;
//车身类
public class Framework {
    private Bottom bottom;
    public Framework(){
         bottom = new Bottom();
    }
    public void init(){
        System.out.println("构建车身");
        //依赖底座
        bottom.init();
    }
}

package old;
//底盘类
public class Bottom {
private Tire tire;
    public Bottom(){
        Tire tire = new Tire();
    }
    public void init(){
        System.out.println("构建底盘");
        //依赖轮胎
        tire.init();
    }
}

package old;
//轮胎类
public class Tire {
    private int size = 20;//轮胎尺寸
    public void init(){
        System.out.println("轮胎尺寸:"+size);
    }
}

package old;
//测试类,用来创建一个汽车对象
public class Test {
    public static void main(String[] args) {
        Car car = new Car();
        car.init();
    }
}



当我们在创建这个车对象时想要这个车的轮胎尺寸小一点,这个时候就需要我们对轮胎类中的构造方法进行改造,让我们在创建车这个对象的时候,可以直接直接指定车的轮胎大小,如果想修改车的颜色,我们就需要在车身类中添加一个颜色的属性,但是这个构造方法改变之后,对应的之后的类中new的对象的操作都选要进行改变。

package old;

public class Car {
    private Framework framework;
    public Car(int size,String color){
         framework = new Framework(size,color);
    }
    public void init(){
        System.out.println("构造汽车");
        //依赖车身
        framework.init();
    }
}

package old;

public class Framework {
    private Bottom bottom;
    public String color ;
    public Framework(int size,String color){
         bottom = new Bottom(size);
         this.color = color;
    }
    public void init(){
        System.out.println("车身颜色:"+color);
        //依赖底座
        bottom.init();
    }
}


package old;

public class Bottom {
    private Tire tire;
    public Bottom(int size){
        tire = new Tire(size);
    }
    public void init(){
        System.out.println("构建底盘");
        //依赖轮胎

        tire.init();
    }
}

package old;

public class Tire {
    private int size = 20;
    public Tire(int size){
        this.size = size;
    }
    public void init(){
        System.out.println("轮胎尺寸:"+size);
    }
}

package old;

public class Test {
    public static void main(String[] args) {
        Car car = new Car(12,"red");
        car.init();
    }
}

可以看见上述的代码是"牵一发而动全身",当最底层代码改动之后,整个调用链上的所有代码都需要改动,这就是代码中的耦合性太高而导致的。

2️⃣使用IoC思想实现的代码

解决这个问题,我们可以使用IoC的思想来实现代码,我们只需要将原来自己创建的下级类,改为传递的方式(也就是注入的方式),我们在上级类中用构造方法的参数来申明这个类需要使用它的下级类。不在这个类中new这个下级类的对象,而是在Test类中统一的使用构造方法来创建这些类的对象。

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();
    }
}


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();
    }
}


package ioc;

//底盘类
public class Bottom {
    private Tire tire;
    public Bottom(Tire tire){
        this.tire = tire;
    }
    public void init(){
        System.out.println("Tire init");
        tire.init();
    }
}

package ioc;

//轮胎类
public class Tire {
    private int size = 20;
    public void init(){
        System.out.println("Tire init,size:"+size);

    }
}

package ioc;
/*
 * 模拟IoC容器,这个类中的Test构造方法,可以认为是Spring中进行的操作,我们无需关注
 * 只需要关注前面创建的汽车类。
 * */
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();
    }
}

可以将这个Test类中除了main方法之外的认为是Spring框架也就是IoC容器,Test构造方法中的这些内容都是在这个容器中实现好的,我们使用Spring是无需关注,只需要关注我们创建的类中需要添加和修改的属性。就比如我们想要车身为红色,只需要在Framework类中,添加一个color属性,构造这个类的构造方法的时候,需要对这个color属性添加一个初始化的操作即可。也不需要修改这个调用链上的其他类。

从这里也就可以看出我们将控制权翻转了,将控制权交给了容器,程序员不在控制这些对象的生命周期。

 可以看见我们创建的车的对象,想要修改一些属性,只需要修改对应的类中的构造方法,之后的都是有Test类中,也就是容器中设置车的属性即可。不在需要调整整个调用链,这就达到了解耦合的效果。

✨总结:

  • 传统的代码中类的实现是上级类控制着下级类,下级类对象的创建和销毁都是由上级类控制,也就是程序员控制。而改进之后的解耦合的代码中上级类不在控制下级类对象的创建和销毁,而是把下级对象注入到当前的对象中,下级对象的控制权不在由上级类控制,这样即使下级类发生了任何变化,上级类都是不受影响的,这就是IoC的实现思想。
  • IoC的好处就是,对象的生命周期(对象的创建和销毁)不再由程序员来控制,而是交给了IoC容器也就是由Spring框架来处理,实现了解耦,使程序的可维护性提高。

 3、Spring IoC

Spring是包含了多个工具方法的IoC(控制反转)容器,他是一个容器,那么就存在最基本的两个功能。

  1. 将对象(Bean)存入Spring容器中;
  2. 从Spring容器中取出对象(bean);

将对象存放到容器中的好处:将对象存储到IoC容器相当于将以后可能用的所有工具制作好都放在仓库中,需要的时候直接取就可以,用完了再把它放回到仓库,而new对象的方式相当于,每次需要工具的时候, 都需要现场从0开始制作,使用完成之后,将这个工具不保存直接扔掉,下次使用的时候再创建,这就是IoC容器和普通程序开发的区别。

Spring是一个IoC容器,对象的创建和销毁的权利都交给Spring来管理,它本身又具备了存储对象和获取对象的能力。


4、DI(依赖注入)

DI是Dependency Injection的缩写,翻译成中文就是"注入依赖"的意思。

所谓依赖注入,就是由IoC容器再运行期间,动态的将某种依赖关系注入到对象之中。就像我们之前的IoC思想代码,在运行Car类的时候,需要的依赖的是Framework类,他会再容器中找到,并赋值给Car类中的framework属性。这个过程就是动态的将依赖注入到对象中,这也就是依赖注入。

4.1、IoC和DI的区别

  • 相同点:IoC和DI是从不同的角度描述了同一间事情,就是指通过引入IoC容器,利用依赖关系注入的方式,实现对象之间的解耦。
  • 不同点:IoC是"目标"也是一种设计思想,而且目标和思想只是一种指导原则,最终还是要有可行的落地方案,而DI就是IoC的一种具体实现。

5、 DL(依赖查找)

依赖查找(DL)也是IoC(控制翻转)的一种实现方式,DL是Dependency Lookup的简称。

在依赖查找中,对象负责查找她所依赖的对象,而不是将依赖关系委托给容器。容器只负责管理大对象的生命周期,而不负责对象之间的依赖关系。

依赖注入和依赖查找的区别在于,依赖注入是将依赖关系委托给容器,由容器来管理兑现之间的依赖关系;而依赖查找是由对象自己来查找他所依赖的对象,容器只负责管理对象的生命周期。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3徽标数(Badge)

APIs 参数说明类型默认值必传color自定义小圆点的颜色string‘’falsecount展示的数字,大于 overflowCount 时显示为 overflowCount,为 0 时隐藏number | slot0falseoverflowCount展示封顶的数字值number99falseshowZero当数值为 0 时,是否展…

Django实现音乐网站 ⑵

使用Python Django框架制作一个音乐网站,在系列文章1的基础上继续开发,本篇主要是后台歌手表模块开发。 目录 表结构设计 歌手表(singer)结构 创建表模型 设置图片上传路径 创建上传文件目录 生成表迁移 执行创建表 后台管…

PUBG(最短路BFS)

题目:https://ac.nowcoder.com/acm/contest/62106/E 最近,喜爱ACM的PBY同学沉迷吃鸡,无法自拔,于是又来到了熟悉的ERANGEL。经过一番搜寻,PBY同学准备动身前往安全区,但是,地图中埋伏了许多LYB&…

2023年第四届“华数杯”数学建模思路 - 案例:FPTree-频繁模式树算法

## 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法,就是频繁模式树算法,他与Apriori算法一样也是用来挖掘频繁项集的&#xff0c…

阿里云OSS的开通+配置及其使用

云存储解决方案-阿里云OSS 文章目录 云存储解决方案-阿里云OSS1. 阿里云OSS简介2. OSS开通(1)打开https://www.aliyun.com/ ,申请阿里云账号并完成实名认证。(2)充值 (可以不用做)(3)开通OSS&am…

STM32F1基于标准库ST7735 1.8‘‘LCD显示DHT11数据

STM32基于标准库ST7735 1.8‘’LCD显示DHT11数据 📍HAL库驱动可以参考:《STM32基于HAL工程读取DHT11数据》🌼显示效果: 🌻ST7735 128x160 1.8’LCD屏幕 📌屏幕资料和相关驱动可以参考《1.8寸TFT LCD128…

《golang设计模式》第一部分·创建型模式-04-抽象工厂模式(Abstract Factory)

文章目录 1. 概述1.1 角色1.2 类图 2. 代码示例2.1 设计2.2 代码2.3 类图 1. 概述 1.1 角色 AbstractFactory(抽象工厂):它声明了一组用于创建产品的方法,每一个方法对应一种产品。ConcreteFactory(具体工厂&#xf…

ArmSoM-W3之RK3588安装Qt+opencv+采集摄像头画面

1. 简介 场景:在RK3588上做qt开发工作 RK3588安装Qtopencv采集摄像头画面 2. 环境介绍 这里使用了OpenCV所带的库函数捕获摄像头的视频图像。 硬件环境: ArmSoM-RK3588开发板、(MIPI-DSI)摄像头 软件版本: OS&…

[C++]

C 一.C基础入门1.HelloWorld2.注释3.变量4.常量5.关键字6.命名规则 二.数据类型1.整形2.sizeof关键字3.浮点型4.字符型5.转义字符6.字符串型7.布尔类型8.数据的输入 三.运算符1.算数运算符2.赋值运算符3.比较运算符4.逻辑运算符 一.C基础入门 1.HelloWorld 首先到官网下载并安…

贯穿设计模式--开闭原则

🌵概述 该原则主要说明的是扩展开放,对修改关闭,即尽量通过扩展软件实体类等来解决需求变化,而不是通过修改已有的代码来完成变化;实现开闭原则的核心思想就是面向抽象编程,强调的是用抽象构建框架&#x…

Windows驱动开发必备工具

Windows驱动开发必备工具 设备树文软件 可以查看设备信息 数字签名工具安装包 开发用的数字签名证书密钥 断点命中工具包(双机调试必备) 二进制文件解析工具 日志查看工具(必备) IRP查看工具 C驱动开发相关书籍 有需要工具、书籍…

怎么学习CSS相关技术知识? - 易智编译EaseEditing

学习CSS技术是前端开发中的重要一环,它用于控制网页的样式和布局,使网页更加美观和易于使用。以下是学习CSS技术的几个方面: 基本语法和选择器: 了解CSS的基本语法,学习如何使用选择器来选择HTML元素并应用样式。 样…

vim、awk、tail、grep的使用

vim命令 $定位到光标所在行的行末^定位到光标所在行的行首gg定位到文件的首行G定位到文件的末行dd删除光标所在行ndd删除n行(从光标所在行开始)D删除光标所在行,使之变为空白行x删除光标所在位置字符nx删除n个字符,从光标开始向后…

使用Flutter的image_picker插件实现设备的相册的访问和拍照

文章目录 需求描述Flutter插件image_picker的介绍使用步骤1、添加依赖2、导入 例子完整的代码效果 总结 需求描述 在应用开发时,我们有很多场景要使用到更换图片的功能,即将原本的图像替换设置成其他的图像,从设备的相册或相机中选择图片或拍…

CAD .NET 15.0 企业版 Crack

CAD .NET 15.0 企业版 企业版 企业版 企业版 企业版 Updated: June 14, 2023 | Version 15.0 NEW CAD .NET is a library for developing solutions in .NET environment. It supports AutoCAD DWG/ DXF, PLT and other CAD formats. The library can be used in a wide rang…

visual studio 生成dll文件以及修改输出dll文件名称操作

目录 visual studio 生成dll文件以及修改dll文件名称一、准备测试代码二、设置导出dll属性三、生成dll文件 .lib .dll .pdb 的简单介绍dll文件使用方式lib文件使用方式1、动态链接 (原理)2、静态链接: visual studio 生成dll文件以及修改dll文…

flex 弹性布局

Flex 布局的使用 任何一个容器都可以指定为 Flex 布局。 .box{ display: flex; //flex作为display的一个属性使用 } 行内元素也可以使用 Flex 布局。 .box{ display: inline-flex; } 注意:设为 Flex 布局以后,子元素的float、clear和vertical-align…

MySQL做分布式锁

分布式锁mysql实现方式 方式1:唯一索引 创建锁表,内部存在字段表示资源名及资源描述,同一资源名使用数据库唯一性限制。多个进程同时往数据库锁表中写入对某个资源的占有记录,当某个进程成功写入时则表示其获取锁成功其他进程由于…

备战秋招 | 笔试强化22

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、在有序双向链表中定位删除一个元素的平均时间复杂度为 A. O(1) B. O(N) C. O(logN) D. O(N*logN) 2、在一个以 h 为头指针的单循环链表中,p 指针指向链尾结点的条件是( ) A. p->ne…

小程序云开发快速入门(2/4)

前言 我们对《微信小程序云开发快速入门(1/4)》的知识进行回顾一下。在上章节我们知道了云开发的优势以及能力,并且我们还完成了码仔备忘录的本地版到网络版的改造,主要学习了云数据库同时还通过在小程序使用云API直接操作了云数…
最新文章