详解 Spring - Ioc(控制权反转) 和 DI(依赖注入)

news2024/7/4 6:08:35

目录

Spring 是什么?

Ioc

Ioc 的优点

DI 

Ioc 和 DI 的区别


Spring 是什么?

通常情况下 Spring 是指 Spring Framework (Spring 框架), 是一个开源框架, 有着庞大的社区, 这就是他能长久不衰的原因, Spring 支持广泛的应用场景, 他可以让企业级的应用开发起来更简单

Spring框架旨在简化Java开发,并提供一种灵活的、综合性的解决方案,使得开发者可以专注于业务逻辑的实现,而不用过多关注底层的技术细节。

重点:

Spring 的核心特性 : Spring 是包含了众多工具方法的 IoC 容器

Ioc

IOC是Inversion of Control(控制反转)的缩写,也称为依赖注入(Dependency Injection,DI)。它是一种设计原则和编程模式,用于降低组件之间的耦合度,提高代码的可维护性和灵活性。

在传统的编程模式中,一个对象通常负责创建和管理其依赖的其他对象,这种控制关系由对象自己管理,因此称为控制权在对象内部。而在IOC中,控制权被反转,即由外部容器负责创建和管理对象之间的依赖关系。

具体来说,IOC容器在应用程序启动时负责创建各个对象,并将它们的依赖关系注入到相应的对象中,使得对象之间的耦合度降低。这样一来,对象只需要关注自己的业务逻辑,而不需要关心依赖对象的创建和管理,从而使得代码更加松散耦合、易于测试和维护。

Spring框架的核心功能之一就是提供了一个IOC容器,通过配置文件或注解,开发者可以声明对象之间的依赖关系,让Spring容器来负责对象的创建和依赖注入,从而实现控制反转。这使得Spring成为了一个灵活、可扩展的企业级应用开发框架。

一句话总结:

Ioc (控制权翻转) -> 对象的生命周期,不由程序员(或当前代码)来控制,而是由 Spring (Spring 容器/Ioc 容器)来控制

Ioc 的优点

  1. 降低组件之间的耦合(松耦合):IOC将对象之间的依赖关系交由外部容器来管理,使得组件之间的耦合度降低组件不再直接依赖于具体的实现细节,而是通过接口或抽象类进行交互,这样可以更容易地进行模块的替换和扩展,提高代码的灵活性。

  2. 提高可维护性:通过IOC容器管理对象的依赖关系,代码结构更加清晰和易于理解。在修改或更新依赖的时候,不需要修改大量的代码,只需要调整配置即可,减少了代码的改动范围,从而降低了出错的风险,提高了代码的可维护性。

  3. 易于测试:IOC使得依赖对象的创建和管理与组件的业务逻辑分离,因此在单元测试中可以轻松地使用模拟对象或者假对象来替代真实的依赖对象,从而更加方便地进行单元测试。

  4. 支持松散耦合:IOC容器可以通过配置文件或注解来管理对象的依赖关系,这使得组件之间的耦合度更松散。这种松散耦合使得开发者能够更容易地替换、更新和维护组件,也使得代码更易于复用和扩展。

  5. 提高了代码的可扩展性:由于IOC支持松散耦合和模块化的设计,当需要增加新功能或引入新的组件时,可以更加方便地进行扩展而不需要修改大量现有的代码。

总的来说,IOC的优点在于提高了代码的灵活性、可维护性和可测试性,使得应用程序更易于开发、扩展和维护。这也是为什么IOC在现代的应用程序开发中得到广泛应用的原因。

组件: 一个组件可以是一个独立的类,也可以是一组相关联的类。组件通常用于封装特定的功能或服务,并且具有明确定义的接口,允许其他组件或系统通过该接口与它进行交互。

控制反转我们可以用具体的代码示例来进行举例说明:

实现电脑配件之间的关系

先用传统模式实现,之后和控制反转进行对比

传统模式:

实现思想:

组装一台电脑,需要很多东西,我们举例三者之间的依赖关系,电脑需要依赖机身, 而机身得依赖屏幕等等...我们使用代码实现

package old2;

import ioc.Test;

//电脑类
public class Computer {
    private Framework framework;

    public Computer(int size) {
        this.framework = new Framework(size);
    }

    public void fun() {
        System.out.println("I am computer");
        framework.fun();
    }
}

//机身类
class Framework {
    private Screen screen;
    public Framework(int size) {
        this.screen = new Screen(size);
    }

    public void fun() {
        System.out.println("I am framework");
        screen.fun();
    }
}

//屏幕类
class Screen {
    public int size = 10;
    public Screen(int size) {
        this.size = size;
    }
    public void fun() {
        System.out.println("I am screen size : " + size);
    }

}
//测试类
class Test1 {
    public static void main(String[] args) {
        Computer computer = new Computer(20);
        computer.fun();
    }
}

缺点:

使用传统方法之后, 我只是改了一下屏幕的尺寸, 他依赖的各个组件中都要设置 size 进行改动, 需求要是太多了的话.修改的地方更是越来越多,这就是传统开发中的缺陷

解决办法:

就是,使用控制反转, 我们由自己创建下级类, 改为传递的方式,自己不用创建下级类. 这时候下级类发生了改变我们也无需改动

这样就相当于我们屏幕组件都外包出去, 改的时候只需要给外包公司说一下他就帮我们改了

现在我们用 Ioc(控制反转)思想实现

package ioc2;

public class Computer {
    private Framework framework;

    public Computer(Framework framework) {
        this.framework = framework;
    }

    public void fun() {
        System.out.println("I am computer");
        framework.fun();
    }

}

//机身类
class Framework {
    private Screen screen;
    public Framework(Screen screen) {
        this.screen = screen;
    }

    public void fun() {
        System.out.println("I am framework");
        screen.fun();
    }
}

//屏幕类
class Screen {
    public int size;
    public Screen(int size) {
        this.size = size;
    }
    public void fun() {
        System.out.println("I am screen size : " + size);
    }

}
 //相当与一个Ioc容器
class Test {
    private Computer computer;
    private Framework framework;
    private Screen screen;
    public Test() {
        this.screen = new Screen(10);
        this.framework = new Framework(screen);
        this.computer = new Computer(framework);
    }

     public static void main(String[] args) {
         Test test = new Test();
         test.computer.fun();
     }
}

现在改尺寸的话只需要改一个地方即可,整个调用链不需要改变,实现了解耦

总结: 通过以上的对比我们发现 : 改进之后的控制权发⽣的反转,不再是上级对象创建并控制下级对象了,⽽是下级对象把注⼊将当前对象中,下级的控制权不再由上级类控制了,这样即使下级类发⽣任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实现思想


理解完控制反转之后我们来看看开头说的这句话,Spring 是包含了众多工具方法的 IoC 容器, 既然Spring 是一个容器,那么他就会具备两个最基本的功能

1. 将对象存入到容器中

2. 从容器中取出对象

这就是 Spring 最核心的两个功能, 具体实现的方式就是接下来我们说的 DI ,我们简单来了解一下

DI 

DI代表依赖注入(Dependency Injection),它是控制反转(IoC)的一种具体实现方式。

依赖注入是一种设计模式,通过外部容器(通常是IOC容器)来管理组件之间的依赖关系。在传统的编程模式中,一个对象负责创建和管理其所依赖的其他对象,这样会导致代码高度耦合且难以维护。而在依赖注入中,对象不再负责自己的依赖对象的创建和管理,而是由外部容器来负责,将依赖的对象“注入”到对象中。

依赖注入可以通过构造函数、Setter方法或接口注入等方式来实现。通过依赖注入,对象只需关注自身的业务逻辑,而不需要关心依赖的具体实现细节,从而降低了组件之间的耦合度,提高了代码的可维护性和灵活性。

Spring框架是一个经典的使用依赖注入的例子。通过配置文件或注解,Spring容器负责创建和管理对象之间的依赖关系,从而实现了控制反转和依赖注入。这使得Spring应用程序更易于开发、测试和维护。

Ioc 和 DI 都了解过了之后, 我们来说说 他们两者的区别

Ioc 和 DI 的区别

IOC (Inversion of Control) 和 DI (Dependency Injection) 是软件开发中两个相关但不同的概念。

  1. IOC(控制反转): IOC 是一种软件设计原则,其核心思想是将控制权从一个模块或类的内部转移到外部容器。传统的程序设计中,类通常会自己创建和管理其依赖关系。但在IOC中,类不再自己直接管理依赖关系,而是由外部容器来管理和注入这些依赖关系。这样做的目的是解耦组件之间的依赖,提高代码的可维护性和可扩展性。

  2. DI(依赖注入): DI 是实现IOC的一种具体方式。它是IOC的一种具体实现模式。在DI中,依赖关系不是在类内部通过实例化其他类来创建,而是通过在类的构造函数、属性或方法中传递依赖对象。换句话说,依赖关系是由外部容器注入到类中的。这种方式使得类的使用者不需要关心依赖对象的创建和生命周期,而是由容器来负责。

总结:

  • IOC 是一种设计原则,其核心思想是将控制权从类内部转移到外部容器,从而实现解耦和可维护性。

  • DI IOC的一种具体实现方式,它通过在类的构造函数、属性或方法中传递依赖对象来实现控制反转。DI 是实现IOC的一种手段

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

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

相关文章

Selenium之css如何实现元素定位,你了解多少?

前言 世界上最远的距离大概就是明明看到一个页面元素站在那里,但是我却定位不到!! Selenium定位元素的方法有很多种,像是通过id、name、class_name、tag_name、link_text等等,但是这些方法局限性太大, 随…

简单认识框架

hi,大家好,好久不见今天为大家带来框架相关的知识 文章目录 🌸1.框架🥝1.1为什么要学习框架 🌸2.框架的优点🥝2.1采用servlet创建项目👀2.1.1缺陷 🥝2.2采用SpringBoot创建项目👀2.2.1优势 &…

Vue-Cli脚手架的安装和使用

文章目录 一、Vue-Cli脚手架的环境准备1. 安装Node.js1-1 去 [Node.js官网](https://nodejs.org/zh-cn/) 下载安装包,修改安装路径到其它盘,如 G:\Program Files1-2 安装npm淘宝镜像,提速 2. 设置 cnpm的下载路径和缓存路径2-1 在安装目录 G:…

Zoho Projects:Jira的理想替代品,让项目管理更高效

在软件开发生命周期中,项目管理一直是一个非常重要的环节。为了更好地协作、追踪项目的进程和管理任务,许多公司选择了Jira这款著名的项目管理工具,它是个非常强大的工具,但同时也有非常明显的缺点。今天,我们将向大家…

知识普及:[18F]FB RGD,18F标记RGD多肽,tumor显像剂,

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ 为大家介绍(CAS:N/A),试剂仅用于科学研究,不可用于人类,非药用,非食用 分子式:C34H44FN9O9 分子量:740.8 中文名称&#xff1a…

linux之Ubuntu系列 系统信息 (一)查看文件、磁盘 、进程

时间和日期 查看当前的系统时间 date 查看日历 -y 显示本年度日历, 不加-y 选项,显示本月日历 cal [-y] 查看磁盘 和 目录 空间 df [-h] df:disk free 显示磁盘可用空间,-h,跟 ls -lh 效果类似,以人性化方…

Python 字典 get()函数使用详解,字典获取值

「作者主页」:士别三日wyx 「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」:小白零基础《Python入门到精通》 get函数使用详解 1、设置默认返回值2、嵌套字典取值3、get() 和 dict[key] 的区别…

使用WebRTC实现多人视频会议

1.初步准备 1.1.使用同事nodejs开发的一个信令服务器。提供Https的WebSocket功能 1.2.准备一个多人视频会议的客户端Web程序client.html 2.遇到问题 2.1.在Tomcat下打开client.html,如果不使用http://127.0.0.1:8081/vedio/client.html,而使用实际IP…

DETR的位置编码

记录一下,以防忘记。 首先,致谢知乎vincent DETR论文详解 DETR中有这样一个类和一个包装函数 class NestedTensor(object):def __init__(self, tensors, mask: Optional[Tensor]):self.tensors tensorsself.mask maskdef to(self, device):# type: …

C知道,CSDN 出来的AI尝试

已经上图,算力不知道怎么样。 C知道 (csdn.net)

JDK、JRE与JVM三者之间的关系及区别

文章目录 0、关系1、JDK2、JRE3、JVM 0、关系 JDK JRE Java 开发工具包 [Java,Javac,Javadoc,Javap等]JRE JVM Java 的核心类库 1、JDK 什么是JDK,JDK是用于Java程序开发的最小环境,包含:Java程序设计语言,Java虚拟机&#…

git : 从入门到实战进阶

目录 0. 前言 1. git stash: 暂时保存本地修改 2. git push时发生冲突怎么办? 3. 访问过去的提交版本:git checkout 3.1 detached HEAD 3.2 “detached HEAD”状态下所作的修改会怎样呢? 3.3 “detached HEAD”状态下所作的修改如何汇…

leetcode100.相同的树

⭐️ 题目描述 🌟 leetcode链接:相同的树 1️⃣ 代码: bool isSameTree(struct TreeNode* p, struct TreeNode* q){// 判断两棵树当前结点是否为空if (p NULL && q NULL) {// 说明是相同的return true;}// 来到这里有几种情况// …

causal-learn ModuleNotFoundError: No module named ‘pygam‘

调用 causallearn 库包,测试CAM-UV算法时报错: No module named pygam 解决方法: pip install pygam 参考链接: 【Python Causal Learning Toolbox】causallearn 库包的使用、报错修改_板砖板砖我是兔子的博客-CSDN博客

java ArratList深拷贝

引用深拷贝 便捷方法 class Test {public static void main(String[] args) {ArrayList<User> list new ArrayList<>();for (int i 0; i < 3; i) {User user new User(i, "name" i);list.add(user);}ArrayList<User> list1 new ArrayList…

超细致的性能测试流程,你get了吗?

性能测试&#xff1a;利用工具模拟大量用户操作&#xff0c;验证系统承受的负载情况。 性能测试的目的&#xff1a;找到潜在的性能问题或瓶颈&#xff0c;分析并解决&#xff1b;找出性能变化趋势&#xff0c;为后续扩展系统提供参考。测试监控&#xff1a;基准测试、配置测试…

【JavaEE】DI与DL的介绍-Spring项目的创建-Bean对象的存储与获取

Spring的开发要点总结 文章目录 【JavaEE】Spring的开发要点总结&#xff08;1&#xff09;1. DI 和 DL1.1 DI 依赖注入1.2 DL 依赖查询1.3 DI 与 DL的区别1.4 IoC 与 DI/DL 的区别 2. Spring项目的创建2.1 创建Maven项目2.2 设置国内源2.2.1 勾选2.2.2 删除本地jar包2.2.3 re…

(栈队列堆) 剑指 Offer 31. 栈的压入、弹出序列 ——【Leetcode每日一题】

❓ 剑指 Offer 31. 栈的压入、弹出序列 难度&#xff1a;中等 输入两个整数序列&#xff0c;第一个序列表示栈的压入顺序&#xff0c;请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如&#xff0c;序列 {1,2,3,4,5} 是某栈的压栈序列&#xff0c;序…

好的CRM需要有哪些特点?

CRM客户管理系统在企业中占有举足轻重的地位&#xff0c;既是战略工具又可以强化部门间的团队协作、优化销售流程、缩短销售周期。市面上crm做得比较好的公司有哪些&#xff1f; 1.上榜Gartner魔力象限 好的CRM市场的引领、产品研发的持续投入、技术创新以及不断增长的市场份…