详解Spring Ioc(控制反转)

2023-11-02

Spring Ioc

控制反转是一个比较抽象的概念,可以举例来说明。
生活中,人们要用到一种东西,人们的基本想法就是找到东西,比如想喝果汁,在没有饮品店的日子里,最直接的做法就是,买果汁机,水果,准备开水。这时我们“主动”创造的过程,也就是一杯果汁需要主动去创造。
而现在果汁店遍地都是,想喝果汁,第一想法就是打开手机,搜索果汁店,根据自己喜欢的口味下单,等待外卖小哥来送果汁,注意:这里我们没有“主动”创造果汁,是由饮品店创造的,而不是我们,但是也达到了要求是不是。

通过上面的简单的例子,我们从中可以看到控制反转的思想,现实中系统的开发者是一个团队,团队由许多开发者组成。假设我在一个电商网站负责开发工作,我比较熟悉商品交易流程,但对财务不怎么熟悉,而团队中有些人员对于财务处理十分熟悉,在交易的过程中,商品交易流程只需要调度财务的相关接口,才能得以实现,那么我们的期望应该是:

  1. 熟悉财务流程的成员开发对应的接口
  2. 接口逻辑尽量简单,内部复杂的业务并不需要自己去了解,我只需要通过简单的调用就能使用
  3. 通过简单的描述就能获取这个接口实例,且描述应该尽量简单

其实这完全跟果汁的例子进行类比,果汁就相当于财务接口,而熟悉财务流程的同事就等同于饮品店,而我们根据喜欢的口味下单就等同于财务接口实例的描述。
生活中的例子与程序开发是多么的相似,但这里有个需要注意点:财务接口对象的创建不是自己的行为,而是财务同事主动创建,也达到了你的要求,在潜意识里你会觉得对象应该由你来创建,但是事实上这并不是你真正的需求。因为你对这一领域不精通,这个时候可以把创建对象的主动权交给别人,这就是控制反转的概念。对于财务开发者而言,他们也不了解交易系统的细则,他们同样希望由你来创建交易接口。为了更好的阐述上面的抽象描述,我们使用java代码的形式模拟主动创建和被动创建的过程。

主动创建对象

如果我们需要一杯果汁,那就等同于需要水果,开水,糖等,搅拌机(工具·)
主动创造果汁,需要创建对应的对象–JuiceMaker(果汁生成器)和Blender(搅拌机)

public class Blender {
    /**
     * 搅拌机
     * @param water 水
     * @param fruit 水果
     * @param sugar 糖
     * @return
     */
    public String mix(String water,String fruit,String sugar){
        String juice = "这是一杯由"+water+"\n水果:"+fruit+"\n糖量:"+sugar+"\n组成的果汁";
        return juice;
    }
}
@Getter
@Setter
public class JuiceMarker {
    private Blender blender = null;//搅拌机
    private String water;//水描述
    private String fruit;//水果
    private String sugar;//糖分描述

    public String makeJuice(){
        blender = new Blender();
        return blender.mix(water,fruit,sugar);
    }
}

主动创造果汁,需要我们实现自己可能不太熟悉的工作–如何搅拌果汁,比如这里的mix方法,显然不是一个好的方法,而对象果汁(juice)是需要依赖水(water)、水果(fruit)、糖(sugar)和搅拌机(blender)去实现的,这样的关系也会需要我们自己去维护,如下图:
在这里插入图片描述
现实中,一个复杂的系统界面对着成百上千种情况,如果都需要这样的维护,那么会十分复杂,更多的时候,我们并不希望了解这类过程,因为有些东西我们并不需要知道过程,只需要获得最后的结果。正如果汁的例子那样,现实生活中我们更加希望是通过对饮品店的描述得到果汁,只想对结果进行描述,得到我们所需要的东西,这就是被动创建对象。

被动创建对象

假设已经提供了果汁制造器(juiceMaker2)那么只需要对其进行描述就可以得到果汁了。假设饮品店还会给我们提供这样一个描述(source),它的描述如下:

@Getter
@Setter
public class JuiceMarker2 {
    private String beverageShop = null;
    private Source source = null;
    
    public String makeJuice(){
        String juice = "这是一杯由"+beverageShop+"饮品店,提供的"+source.getSize()+source.getSugar()+source.getFruit();
        return juice;
    }
}
@Setter
@Getter
public class Source {
    private String fruit;//类型
    private String sugar;//糖分描述
    private String size;//大小杯
}

显然我们不需要去关注果汁是如何制造出来的。系统采用XML对这个清单进行描述,如下代码:

<bean id="source" class="com.lifly.ioc.Source">
        <property name="fruit" value="橙汁"/>
        <property name="sugar" value="少糖"/>
        <property name="size" value="大杯"/>
    </bean>

这里对果汁进行了描述,接着就是选择饮品店,假设选择的是蓝莓,那么会有以下描述:

    <bean id="juiceMaker2" class="com.lifly.ioc.JuiceMarker2">
        <property name="beverageShop" value="蓝莓"/>
        <property name="source" ref="source"/>
    </bean>

这里将饮品店设置为蓝莓,这样就指定了蓝莓为我们提供服务,而订单则引用我们之前的定义,这样使用下面的代码借得到了一杯果汁了

    @Test
    public void test01(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        JuiceMarker2 juiceMaker2 = (JuiceMarker2) context.getBean("juiceMaker2");
        String s = juiceMaker2.makeJuice();
        System.out.println(s);
    }
}

这个过程,果汁是由蓝莓所制造的,我们并不关系制造的过程,我们所关心的是对果汁如何描述,选择哪个店去制造,这才是现今人们的习惯,这个理念也可以用于程序代码
在这里插入图片描述
显然这个过程中我们不需要了解饮品店是如何工作的,我们只需要关注如何描述,就能得到想要的结果。

Spring Ioc简述

有了上面的实例,下面来说下控制反转的概念:
控制反转****是一种通过描述(在Java中可以使XML或者注解)并通过第三方去产生或获取特定对象的方法。
正如被动创建的果汁是通过XML配置的描述所得到的,而在spring中实现控制反转的是Ioc容器,其实现方式是依赖注入(Dependency Injection,DI),正如上述的例子,果汁制造器依赖于饮品店和订单去制造果汁的,而饮品店是别人去创造的,我们只需要它能生产果汁就可以了,并不需要去理解如何创建果汁。
spring会提供Ioc容器来管理对应的资源,正如上面的例子中的饮品店和订单资源,由于它们形成依赖关系,其中果汁制造器用到饮品店和订单两个资源。同样的,这个也用于编码实战,如以下例子。
当熟悉财务的同事完成对财务接口模块的开发,就可以将其发布到Spring Ioc的容器里,这个时候你只需要过程描述得到对应的财务接口,就可以完成对应的财务操作了。而财务模块是如何工作的,它有需要那些依赖对象,都是由熟悉模块的同事完成的,这些并不需要你去理解,你只需要它能完成对应的财务操作就可以了。同样,对于熟悉交易的你,也可把交易接口模块发布到Spring Ioc容器中,这样财务开发人员就可以通过容器获取交易接口得到交易明细了,交易模块如何工作,又依赖于哪些对象,他也是不需要知道的,可见Spring Ioc容器带来了许多使用的便利。

在这里插入图片描述

对于测试人员也一样,也许他早早把财务模块测试好了,需要测试交易模块,他并不希望非常细致的了解交易模块,他只需要从Spring Ioc容器中获取就可以了。而他的测试代码也只需要从Spring Ioc容器获取交易模块的内容,至于内部复杂的依赖并不是他所关注的内容,这样就有利于测试人员对模块的测试,降低测试人员测试的复杂度。
这就是一种控制反转的理念,虽然这个理念的一个坏处是理解上的困难,但是它最大的好处在于降低对象之间的耦合,在一个系统中有些类,具体如何实现并不需要去理解,只需要知道它有什么用就可以了。只是这里对象的产生依赖于Ioc容器,而不是开发者主动的行为。主动创建的模式,责任归与开发者,而在被动的模式下,责任归于Ioc容器。基于这样的被动形式,我们就说对象被控制反转了。
基于降低开发难度,对模块解耦,同时也更加有利于测试的原则,Spring Ioc在各大领域中被广泛应用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详解Spring Ioc(控制反转) 的相关文章

随机推荐

  • windTerm—Xshell、SercureCRT等替代品

    最常用的ssh工具 莫过于SercureCRT Xshell 但是这两个都收费 某些场景下不好使用 免费的有putty 但是这个太简陋了 用起来不舒服 finalShell eclecterm tabby 这三个很炫酷 但安装包和占用内存都
  • knn算法,利用numpy简单实现

    首先明确概念 回归 预测体重 预测房价 预测损失 结果是不容易确定的 分类 预测男女 预测是否能通过考试 结果是容易确定的 我的理解 回归针对连续的数据 分类针对离散的数据 回归连续 分类离散 classfication和regressio
  • 在vscode上快速打开php文件(小白手把手教小白,超级详细)

    第一次写博客 如有不足 欢迎指正 在vscode中打开php文件如下 准备工作 先下载小皮面板 记住下载路径 在其中打开Apache和MySQL 然后我们步入正题 1 首先打开vscode 在其中打开小皮面板所在文件夹 在WWW文件里随便建
  • STM32系列 (一)开发环境的搭建

    STM32简介 STM32是意法半导体 ST 推出一款32位的单片机 STM32具有超低的价格 超多的外设 丰富的型号 优异的实时性 极低的开发成本等优势 STM32凭借其产品线的多样化 极高的性价比 简单易用的库开发方式 迅速在众多32位
  • 一、SQL Server列名显示无效却可以运行问题解决?

    一 SQL Server列名显示无效却可以运行问题解决 在SQLServer中 当设计 修改 表结构之后 再用SQL语句时 会出现列名无效 然后却可以运行 如下图 出现这种情况的原因是SQL Server的intellisense 智能感知
  • C语言volatile关键字的作用

    volatile是易变的 不稳定的意思 volatile关键字和const一样是一种类型修饰符 用它修饰的变量表示可以被某些编译器未知的因素改变 比如操作系统 硬件或者其它线程等 遇到这个关键字声明的变量 编译器对访问该变量的代码就不再进行
  • TypeError: Cannot read properties of undefined (reading ‘licenseNum‘) at Proxy

    这是因为在定义的时候 我们只定义了一层的结构 比如 info 其实后端返回的是 info goods goodsName cheng 此时调用goodsName info goods goodsName 就会报错info goods und
  • 2021-12-24 vue项目兼容IE

    Vue 不支持 IE8 及以下版本 因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性 但对于 IE9 Vue 底层是支持 vue cli4脚手架搭建的前端项目 vue版本2 6 12 browserslist配置 指
  • System.Single

    浮点 类型 别名 float System Single double System Double decimal System Decimal 字符 类型 别名 允许的值 bool System Boolean true flase ch
  • 跟阿铭学Linux第六章答案,Linux磁盘管理

    hda一般是指IDE接口的硬盘 hda指第一块硬盘 hdb指第二块硬盘 等等 sda一般是指SATA接口的硬盘 sda指第一块硬盘 sdb指第二块硬盘 等等 du b显示的是文件的实际大小 du k显示的是文件占用的磁盘块的大小 所以磁盘块
  • 性能测试压力测试

    性能测试指标 并发用户数 TPS Transaction Per Second 每秒事务数 系统的性能由TPS决定 mysql 记一次接口压力测试与性能调优 Apache JMeter是Apache组织开发的基于Java的压力测试工具 用于
  • 最长公共子序列 蓝桥杯 1189

    题目描述 给定一个长度为n数组A和一个长度为m数组B 请你求出它们的最长公共子序列长度为多少 输入描述 输入第一行包含两个整数n m 第二行包含n个整数ai 第三行包含m个整数bi 1 lt n m lt 10 3 1 lt ai bi l
  • BearPi-HM Nano HarmonyOS 环境搭建

    BearPi HM Nano HarmonyOS 环境搭建 BearPi HM Nano 介绍 BearPi HM Nano开发板是一块专门为鸿蒙OS设计的鸿蒙OS开发板 板载高度集成的2 4GHz WLAN SoC芯片Hi3861 并板载
  • java mongodb 关闭连接_未释放资源的教训,开发MongoDB连接一定要关闭连接

    废不少工夫将数据存储 全部迁移至mongodb 未作大量改动则是主因 但遇到奇怪的现象 程序跑起不久后 mongodb即假死 另起客户端想登陆mongodb都不成 要重启mongodb服务器才好转 分析原因是mongodb的连接池满掉且不释
  • elasticsearch学习之cross_fields字段使用

    cross fields字段 在查询阶段解决信号冲突问题 问题 The cross fields type is particularly useful with structured documents where multiple fi
  • Java进阶--Java垃圾回收机制全面解析

    本文同步发布在我的个人博客 如需转载请注明出处 提起Java的垃圾回收机制大家应该都有所了解 它不仅是面试的常客 也是Java体系中相当重要的一块知识 深入理解Java的GC机制 不仅有助于我们在开发中提高程序的性能 更有了在面试官面前炫
  • MySQL索引怎么用?究竟能有多快?看完这篇你就懂了!

    本文介绍的是MySQL索引的具体使用 原理以及本质结构请看我写的上一篇文章 MySQL索引凭什么能让查询效率提高这么多 原理是什么 目录 索引使用的优势 索引使用的劣势 1 维护成本高 2 所占空间大 索引的分类 索引的创建规则 索引的CR
  • 约瑟夫环(数组解决)

    约瑟夫环问题是一个很经典的问题 一个圈共有N个人 N为不确定的数字 第一个人的编号为0或者1 两个都可以 看你的程序如何编写 假设这边我将第一个人的编号设置为1号 那么第二个人的编号就为2号 第三个人的编号就为3号 第N个人的编号就为N号
  • photoshop不能保存bmp格式

    文章目录 前言 一 显示图层无法导出当前的bmp格式图片 二 图层合并 总结 前言 使用位图进行深度学习的特征点标定时间比正常图片格式的时间要缩短一半 所以使用ps新增异常点 但是新增图层后无法保存bmp的格式 一 显示图层无法导出当前的b
  • 详解Spring Ioc(控制反转)

    Spring Ioc 控制反转是一个比较抽象的概念 可以举例来说明 生活中 人们要用到一种东西 人们的基本想法就是找到东西 比如想喝果汁 在没有饮品店的日子里 最直接的做法就是 买果汁机 水果 准备开水 这时我们 主动 创造的过程 也就是一