首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >控制反转与依赖注入

控制反转与依赖注入

作者头像
李鸿坤
发布于 2020-07-20 01:40:24
发布于 2020-07-20 01:40:24
52400
代码可运行
举报
文章被收录于专栏:泛泛聊后端泛泛聊后端
运行总次数:0
代码可运行

控制反转是Spring框架的核心思想,也是因为Spring的关系这个模式为大众所知晓。

依赖抽象

先看一个比较经典的例子,代码和示意图如下

代码语言:javascript
代码运行次数:0
运行
复制
public class Application{

    pivate  DiskWriter writer = new DiskWriter();

    public void save(){
        writer.saveToDisk();
    }
}

应用程序在需要存储时,直接执行了saveToDisk(),导致了高层应用程序直接依赖低层模块的API 。假设应用程序需要移植到其他平台上,而平台使用的存储介质是SSD,则应用程序无法直接重用,必须要修改代码才可以。这里由于低层的模块存储介质发生了变化,造成了高层模块也必须跟着变化,这不是一个好的设计方式。在设计上希望模块都依赖于模块的抽象,这样才能够重用高层的应用程序。

代码语言:javascript
代码运行次数:0
运行
复制
public interface IDeviceWriter{
    void saveToDevice();
}

public class DiskWriter implements IDeviceWriter{
    public void saveToDevice(){
        System.out.println("save to disk")
    }
}

public class SsdWriter implements IDeviceWriter{
    public void saveToDevice(){
        System.out.println("save to ssd")
    }
}

public class Application{

    private IDeviceWriter deviceWriter;

    public void setDeviceWriter(IDeviceWriter deviceWriter){
        this.deviceWriter = deviceWriter;
    }

    public void save(){
        if(deviceWriter == null){
            throw new RuntimeException("deviceWriter needed ...");
        }
        deviceWriter.saveToDevice();
    }
}

如上述代码把Application与具体的DeviceWriter实现解耦,在存储介质变化的时候并不需要重新修改Application的实现。

应用程序不依赖于实现,但是应用程序与实现都要依赖于接口。这也正是控制反转所要表述的内容。

控制反转

IoC(Inversion of Control )的Control是控制的意思,其背后是一种依赖关系的转移。如果A依赖于B,其意义即B拥有控制权。如果转移这种关系(依赖关系的反转即控制关系的反转),将控制权由实现的一份转移至抽象的一方,让抽象方拥有控制权,可以获得组件的可重用性。IoC的实现方式有2种 1. Service Locator 2. Dependency Injection

服务定位器

服务定位器模式的目的是按需返回服务实例,将服务使用者与具体类分离。

它的实现包含了以下组件

  • Client – 服务的使用者. 它在需要使用到服务的时候从服务定位器获取服务,并调用。
  • Service Locator – 服务定位器从服务工程创建并注册服务到缓存。
  • Service Cache – 用来存储 Service Locator 已经获取过的Service。
  • Initial Context – 负责创建服务,是一个service 工厂的角色。当Service Locator在Cache中没有找到service的时候则调用它进行服务的创建。
  • Service – 服务抽象或者服务的实现

核心的逻辑是 Client 需要服务的具体实现的时候调用 Service Locator 来进行创建,使Client与ServiceImpl解耦。

依赖注入

依赖注入一般是由一个依赖注入容器来负责类的实例化,在实例化的过程中把该类所依赖的抽象的实现给创建好并注入到该类的实例。注入的方式可以总结为三种

  • 构造函数注入 - 实例化的过程中将依赖传入,进行对象的实例化
  • Setter函数注入 - 实例化后容器将依赖通过setter函数设置进去
  • 实现接口注入 - 实例化后, 容器对其中实现了某个接口的类对象进行该接口的调用。 最典型的是Spring的各种Aware接口

这个模式因为Spring的普及而被广泛使用。

对比

Service Locator模式虽然是解耦了应用和依赖的关系,却引入了Service Locator,应用本身依赖了Service Locator。

依赖注入模式,其中的类是没有任何跟自己的实现无关的内容,可以进行单独的测试和使用。对于依赖的实现,它既不知道,也不在乎它们来自何方,有容器给它们注入。就算你换了一个依赖注入容器也是不需要去更改相关类的代码。

延伸

SOLID编程原则里面的 D代表Dependency Inversion Principle 即依赖倒置原则,说的就是控制反转。而控制反转的实现即是Service Locator和Dependency Injection两种模式。

致敬一下经典。

https://martinfowler.com/articles/injection.html

https://java-design-patterns.com/patterns/service-locator/

https://java-design-patterns.com/patterns/dependency-injection/

https://book.douban.com/subject/1830509/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 泛泛聊后端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
控制反转/依赖注入简明教程
在面向对象中IOC是一个重要的设计思想。这篇文章将带领大家快速掌握控制反转和依赖注入。
喵叔
2020/09/08
3270
深入浅出依赖注入
或许您已经在项目中已经使用过「依赖注入」,只不过由于某些原因,致使您对它的印象不是特别深刻。
柳公子
2018/09/17
6990
依赖注入和控制反转
用图例来说明一下,先看没有IoC/DI的时候,常规的A类使用C类的示意图,如图所示:
喝茶去
2019/04/16
1K1
依赖注入和控制反转
Spring控制反转与依赖注入
学习Spring框架,它的核心就是IoC容器。要掌握Spring框架,就必须要理解控制反转的思想以及依赖注入的实现方式。下面,我们将围绕下面几个问题来探讨控制反转与依赖注入的关系以及在Spring中如何应用。
用户3467126
2019/08/12
6840
Spring中的IOC(控制反转),总结和解释易理解
在这之前,我们先记住一句话。好莱坞原则:Don’t call me, we will call you. 即“不用打电话过来,我们会打给你”。
知识浅谈
2022/05/12
1.1K0
Spring中的IOC(控制反转),总结和解释易理解
IOC控制反转与DI依赖注入
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
全栈程序员站长
2022/08/31
2200
IOC控制反转与DI依赖注入
Spring框架入门(三):依赖注入和控制反转
依赖注入(IoC) 和 控制反转(DI) 有什么关系呢?其实它们是同一个概念的不同角度描述。
sr
2019/05/23
6000
Java:控制反转(IoC)与依赖注入(DI)
很长一段时间里,我对控制反转和依赖注入这两个概念很模糊,闭上眼睛想一想,总有一种眩晕的感觉。但为了成为一名优秀的 Java 工程师,我花了一周的时间,彻底把它们搞清楚了。
沉默王二
2019/08/09
5670
Spring的依赖注入与控制反转
平常的java开发中,如果某个类中需要依赖其它类的方法,通常是通过new一个依赖类,然后再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。 依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。 其实可以把DI和IoC理解为同一件事,都是把创建实例的控制权交给容器来操作,只是两种叫法的角度不同:
全栈程序员站长
2022/08/04
4200
依赖注入和控制反转
学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框架的IOC的理解以及谈谈我对Spring Ioc的理解。
AlbertZhang
2020/11/05
9490
学完这篇依赖注入,与面试官扯皮就没有问题了。
讨论控制反转之前,先看看软件系统提出控制反转的前世今生。 一个完整精密的软件系统,组件之间就像齿轮,协同工作,相互耦合。
有态度的马甲
2020/10/30
1.3K0
学完这篇依赖注入,与面试官扯皮就没有问题了。
控制反转、依赖注入、依赖倒置傻傻分不清楚?
如上,我们为一个方法写了一个测试用例,包括main方法的创建,所有的流程都是我们自己来控制的。
蝉沐风
2022/08/22
7080
控制反转、依赖注入、依赖倒置傻傻分不清楚?
轻松理解.NET控制反转和依赖注入
在软件工程领域,特别是在 C# 和 .NET 的上下文中,控制反转(Inversion of Control,IoC)和依赖注入(Dependency Injection,DI)是增强代码模块化、可测试性和可维护性的基本原则。这些范式允许开发人员通过将依赖关系的创建和管理与业务逻辑分离,构建松耦合、灵活的应用程序。
郑子铭
2024/07/12
5600
轻松理解.NET控制反转和依赖注入
编码最佳实践——依赖注入原则
我们在这个系列的前四篇文章中分别介绍了SOLID原则中的前四个原则,今天来介绍最后一个原则——依赖注入原则。依赖注入(DI)是一个很简单的概念,实现起来也很简单。但是简单却掩盖不了它的重要性,如果没有依赖注入,前面的介绍的SOLID技术原则都不可能实际应用。
撸码那些事
2018/12/05
9900
【ASP.NET Core 基础知识】--依赖注入(DI)--在ASP.NET Core中使用依赖注入
在ASP.NET Core中实现依赖注入的第一步是配置依赖注入。ASP.NET Core使用了一个称为依赖注入容器(DI Container)的组件来管理对象之间的依赖关系。DI容器在应用程序启动时被配置,并且可以在应用程序的整个生命周期内使用。以下是配置依赖注入的基本步骤:
喵叔
2024/05/24
9420
Spring 的控制反转/依赖注入
spring:春天 IOC:将创建对象的权力交给 spring 核心容器去控制。工厂模式
张哥编程
2024/12/19
1670
Spring 的控制反转/依赖注入
spring的ioc实现原理_ioc控制反转和di依赖注入
大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说spring的ioc实现原理_ioc控制反转和di依赖注入,希望能够帮助大家进步!!!
Java架构师必看
2022/07/06
5180
spring的ioc实现原理_ioc控制反转和di依赖注入
PHP控制反转与依赖注入
是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式就是依赖注入(Dependency Injection,简称DI)。 书本上的解释:
用户8568307
2022/03/14
6110
介绍依赖注入,依赖查找,控制反转--php实例
不是我自身的,却是我需要的,都是我所依赖的。一切需要外部提供的,都是需要进行依赖注入的。
OwenZhang
2022/01/05
5460
介绍依赖注入,依赖查找,控制反转--php实例
反射机制、依赖注入、控制反转
反向: dll->类[方法,属性]. 从已经有的dll文件反编译得到其中的一些可用的方法.
后端技术探索
2018/08/09
8110
相关推荐
控制反转/依赖注入简明教程
更多 >
目录
  • 依赖抽象
  • 控制反转
    • 服务定位器
    • 依赖注入
    • 对比
  • 延伸
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验