浅谈IOC

IOC的理论背景

图1:传统系统中,对象之间相互引用的一幅图,在采用面向对象方法设计的软件系统中,它的底层的实现都是由n个对象所组成的,所有的对象通彼此之间的合作最终实现系统的业务逻辑,如果我们打开机械式手表的后盖,我们就会看到与图1类似的清形,各个齿轮分别带动时针、分针和秒针顺时针旋转,从而在表盘上产生正确的时间。这些齿轮相互耦合在一起,共同完成某项任务。在这样的齿轮组中,如果有一个齿轮出现一个问题,可能会影响到整个齿轮组的正常运转,齿轮组齿轮间的耦合关系与软件系统中对象之间的耦合关系非常相似。随着系统规模变大,对象之间依赖关系越来越复杂,架构师和设计师对系统的设计和分析面临更大的挑战,对象之间的耦合度过高的系统,必然会出现牵一发而动全身的情形,降低系统之间、模块之间、对象之间的耦合度是软件工程追求的目标。IOC理论的提出,就是为了解决对象之间耦合度过高的问题,实现对象之间的解耦。

图2 解耦的过程

IOC理论提出的观点大致是这样的:借助于第三方来实现对具有依赖关系的对象之间的解耦,对象之间没有了耦合关系。由于引进了第三方IOC容器,使得对象A、B、C、D之间没有了耦合关系,齿轮之间的传动全部依靠了第三方,全部对象的控制权全部交给了第三方IOC容器,IOC容器成了整个系统的关键核心,它起到了一种凝合剂i的作用,把系统中的所有对象凝合在一起发挥作用。

图3 理想的系统

这四个对象之间彼此毫无联系,这样在实现A的时候,无需去考虑B、C、和D,对象之间的依赖关系降低到了最低程度。  参与开发的每一位成员,只要实现自己的类就好了,跟别人没有任何关系。我们再来看看,控制反转到底为什么取这个名字。

软件系统在没有引入IOC容器之前,就像图1所示,对象A 依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须去创建对象B,或者是使用已经创建的B,无论是创建还是使用对象B,控制权全部都在自己手上,在软件系统引入了IOC以后,这种情形就完全改变了,如图2所示,由于IOC容器的加入,对象A和对象B失去了直接的联系,所以当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B,注入到对象A所需要的地方,通过前后的对比,不然看出,对象A获得依赖对象B的过程, 由主动行为变为了被动行为,控制权颠倒过来了,这个就是控制反转的名称的由来。哪些东西被反转了?获得依赖对象的过程被反转。获得依赖对象的过程由自身的管理变为了由IOC容器主动的注入。依赖注入(DI)其实是实现控制反转(IOC)的方式。

依赖注入DI

IOC的另外的名字叫做依赖注入(DI),所谓的依赖注入,就是由IOC容器再运行期间动态地将某种依赖注入到对象之中。所以,依赖注入(DI)和控制反转(IOC)是从不容的角度描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。

图4 电脑  和 外设都是对象,人起到IOC容器的作用

IOC容器就像一个对象制造工厂,你需要什么,它就会传送给你。你直接使用就可以,再也不用关心你是用的东西是如何生成的,最后如何销毁的,这一切都有IOC容器管理。再传统的实现中, 由程序内部代码来控制组件之间的关系,我们经常使用new关键字来实现两个组件之间关系的组合,这种方式会造成组件之间耦合,IOC很好的解决了这种问题,它将 实现组件间的关系 从程序内部提炼到了外部容器,也就是说由容器再运行期间将组件间的某种依赖关系动态地注入到组件中。

IOC好处

IOC在编程过程中不会对业务对象构成很强的侵入性,使用IOC之后,对象具有更好的可实行性,可重用性和可扩展性:

  • 降低组件之间的耦合度
  • 提高开发效率和产品质量
  • 同意标准,提高模块的复用性
  • 模块具有热插拔特性

举个例子:使用USB外部设备比使用电脑内置硬盘带来什么好处呢?第一:USB设备在插入主机之前,与电脑主机没有任何关系,只有被连接在一起后,才有关系,所以无论任何一方发生问题,都不会影响另一方,这在软件工程中就叫做可维护性,非常便于单元测试、调试程序和诊断故障。代码中的每个class都可以单独测试,彼此之间互不影响,只要保证自身的功能无误即可,这就是组件之间低耦合、无耦合带来的好处。 第二 USB和主机之间的无关性还带来了另外一个好处,生产USB和生产电脑的厂商可以是完全互不相干的两个人,他们各干各事,唯一需要遵守的是USB接口的标准,这种特性体现在软件开发过程中,好处很大,每一个开发团队的成员都只需要关心实现自身的业务逻辑,完全不用关心其他人的工作进度。你的任务可以单独测试也不依赖于别人的组件,每个人分工明确,效率提高。第三:提高了模块的复用性。同一个USB外部设备,可以插到任何支持USB的设备,可以插到电脑主机,可以插到DV机,USB外部设备可以被反复利用。我们可以把具有普遍性的、常用的组件独立出来,反复利用到项目中的其他部分或者其他项目,当然这也是面向对象的基本特征。第四:模块具有热插拔特性。IOC生成对象的方式,转为外置方式,也就是把对象生成放到了配置文件进行定义,这样当我们更换一个实现子类将会变得更加简单,只要修改配置文件就可以,完全具有热插拔的特性。(热插拔(hot-plugging或Hot Swap)即带电插拔,热插拔功能就是允许用户在不关闭系统,不切断电源的情况下取出和更换损坏的硬盘、电源或板卡等部件,从而提高了系统对灾难的及时恢复能力、扩展性和灵活性等,例如一些面向高端应用的磁盘镜像系统都可以提供磁盘的热插拔功能。)

IOC的通俗理解如下

  • IOC控制反转:说的是创建对象实例的控制权从代码控制剥离到IOC容器控制,实际就是你在XML文件当中的控制,侧重于原理
  • DI依赖注入:说的是再创建对象实例时,为这个对象注入属性值或其他对象实例,它侧重于实现。

【Spring】IOC的更多相关文章

  1. 【Spring】IOC容器注解汇总,你想要的都在这儿了!!

    写在前面 之前,我们在[Spring]专题中更新了不少关于Spring注解相关的文章,有些小伙伴反馈说,看历史文章的话比较零散,经常会忘记自己看到哪一篇了.当打开一篇新文章时,总感觉自己似乎是看到过了 ...

  2. 【Spring】 IOC Base

    一.关于容器 1. ApplicationContext和BeanFactory 2. 配置文件 XML方式 Java-configuration 方式 @Configuration 3. 初始化容器 ...

  3. 【Spring】IoC容器 - Spring Bean作用域Scope(含SpringCloud中的RefreshScope )

    前言 上一章学习了[依赖来源],本章主要讨论SpringBean的作用域,我们这里讨论的Bean的作用域,很大程度都是默认只讨论依赖来源为[Spring BeanDefinition]的作用域,因为在 ...

  4. 【Spring】IoC容器 - 依赖来源

    前言 上一篇文章已经学习了[依赖注入]相关的知识,这里详细的介绍一下[依赖来源]. 依赖来源 我们把依赖来源分为依赖查找的来源和依赖注入的来源分别讨论. 依赖查找的来源 1. Spring BeanD ...

  5. 【Spring】IoC容器 - 依赖注入

    前言 上一篇文章已经学习了[依赖查找]相关的知识,这里详细的介绍一下[依赖注入]. 依赖注入 - 分类 因为自己是基于小马哥的脉络来学习,并且很认可小马哥梳理的分类方式,下面按照小马哥思想为[依赖注入 ...

  6. 【Spring】IoC容器 - 依赖查找

    前言 上一篇文章已经学习了[IoC的主要实现策略]有2种: 1.依赖查找 2.依赖注入 这里稍加详细的介绍一下依赖查找 1.依赖查找的方式 依赖查找的方式可以以多种维度来划分: 1.按名称/类型/注解 ...

  7. 【Spring】IoC概述

    Spring框架的核心概念--IoC IoC IoC是Inversion of Control的简写,翻译成汉语就是"控制反转".IoC并不是一门技术,而是一种设计思想,在Spri ...

  8. 【Spring】AOP注解方式实现机制

    一.概述 二.@EnableAspectJAutoProxy 注解分析 三.分析AnnotationAwareAspectJAutoProxyCreator 四.执行流程 1. registerBea ...

  9. 【死磕 Spring】----- IOC 之解析 bean 标签:开启解析进程

    原文出自:http://cmsblogs.com import 标签解析完毕了,再看 Spring 中最复杂也是最重要的标签 bean 标签的解析过程. 在方法 parseDefaultElement ...

随机推荐

  1. Java面试题大全(javaSe,HTML,CSS,js,Spring框架等)

    目录 1. Java基础部分 7 1.一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 7 2.Java有没有goto? 7 3.说说&和& ...

  2. Ural 1114 Boxes

    Boxes Time Limit: 600ms Memory Limit: 16384KB This problem will be judged on Ural. Original ID: 1114 ...

  3. 九度oj 题目1078:二叉树遍历

    题目1078:二叉树遍历 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5326 解决:3174 题目描述: 二叉树的前序.中序.后序遍历的定义: 前序遍历:对任一子树,先访问跟,然后遍历 ...

  4. [codevs 1961]躲避大龙(dfs)

    题目:http://dev.codevs.cn/problem/1961/ 分析: 被“SPFA”的标签骗了…… 看了hzwer的博客才知道可以用f[i][0..60]表示每个点每个秒是否可以到.至于 ...

  5. 一篮子苹果,每天吃一半多一个吃,第十天吃一半多一个后就剩余一个,求一共多少个苹果,JAVA版

    /** * @author xuzhu **/public class TestApple { public static void main(String[] args) { int days = ...

  6. Stuts2的"struts.devMode"设置成true后,不起作用的解决的方法

    不用  <constant name="struts.devMode" value="true" /> 改成 <constant name=& ...

  7. Shell细小问题汇总

    Shell细小问题汇总 本文原文出处: http://blog.csdn.net/bluishglc/article/details/44276607 严禁不论什么形式的转载,否则将托付CSDN官方维 ...

  8. ssh远程连接出现someone counld be eavesdropping on you right now 的错误

    master主机通过ssh远程连接slaves机子时出现下述错误 解决的方法: 一.删除/root/.ssh/下的kown_hosts文件 二.在master机子上又一次运行scp id_dsa.pu ...

  9. Android 使用MediaRecorder录音调用stop()方法的时候报错【转】

    本文转载自:http://blog.csdn.net/u014737138/article/details/49738827 这个问题在网上看到了太多的答案,一直提示说按照官网的api的顺序来,其实解 ...

  10. 【Poj2960】S-Nim & 博弈论

    Position: http://poj.org/problem?id=2960 List Poj2960 S-Nim List Description Knowledge Solution Noti ...