在学习Spring的时候,意外找到这个控制反转(IoC)和面向切面(AOP)的容器框架之前,我们先来看一下什么是控制反转(IoC)。

 控制反转(Ioc)和依赖注入(DI)刚听到感到很难理解,平时也程序也很少想到这一点,这几天学Spring的相关资料是看到的最多的是这个概念,网上放狗搜了一下,内容挺多。总算明白了一些。

  Ioc,照我的理解应该是为了满足高内聚低耦合的设计原则,将对象的创建和获取交给外部容器来控制,从外部容器的角度(第三方参照物)来看,达到程序控制权的转移,这样估计好理解了。

  DI,依赖注入,从字面的意思来说是从外部导入的方式实现低耦合,比如构造函数、属性设置等。

  控制反转(Inversion of Control,英文缩写为IoC),也叫依赖注入(Dependency Injection)。我个人认为控制反转的意思是依赖对象发生改变,由最初的类本身来管理依赖对象改变为IoC框架来管理这些对象,使得依赖脱离类本身的控制,从而实现松耦合。

我们先来看一段代码

  1. namespace Dao
    {public interface IPersonDao{void Save();}public class PersonDao : IPersonDao{public void Save(){Console.WriteLine("保存 Person");}}
    }
    namespace SpringNetIoC
    {class Program{private static void NormalMethod(){IPersonDao dao = new PersonDao();dao.Save();Console.WriteLine("我是一般方法");}}
    }

复制代码

Program必然需要知道IPersonDao接口和PersonDao类。为了不暴露具体实现,我可以运用设计模式中的抽象工厂模式(Abstract Factory)来解决。
  1. namespace DaoFactory
    {public static class DataAccess{public static IPersonDao CreatePersonDao(){return new PersonDao();}}
    }

复制代码

FactoryMethod
  1. namespace SpringNetIoC
    {class Program{        private static void FactoryMethod(){IPersonDao dao = DataAccess.CreatePersonDao();dao.Save();Console.WriteLine("我是工厂方法");}}
    }

复制代码

这时,Program只需要知道IPersonDao接口和工厂,而不需要知道PersonDao类。然后我们试图想象,要是有这样的工厂框架帮我们管理依赖的对象就好了,于是控制反转出来了。
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration><configSections><sectionGroup name="spring"><section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" /><section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /></sectionGroup></configSections><spring><context><resource uri="config://spring/objects" /></context><objects xmlns="http://www.springframework.net"><description>一个简单的控制反转例子</description><object id="PersonDao" type="Dao.PersonDao, Dao" /></objects></spring>
</configuration>

复制代码

Program

  1. using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Dao;
    using DaoFactory;
    using Spring.Context;
    using Spring.Context.Support;
    namespace SpringNetIoC
    {class Program{static void Main(string[] args){//NormalMethod();  // 一般方法//FactoryMethod();  // 工厂方法IoCMethod();  // IoC方法"
                Console.ReadLine();}private static void NormalMethod(){IPersonDao dao = new PersonDao();dao.Save();Console.WriteLine("我是一般方法");}private static void FactoryMethod(){IPersonDao dao = DataAccess.CreatePersonDao();dao.Save();Console.WriteLine("我是工厂方法");}private static void IoCMethod(){IApplicationContext ctx = ContextRegistry.GetContext();IPersonDao dao = ctx.GetObject("PersonDao") as IPersonDao;if (dao != null){dao.Save();Console.WriteLine("我是IoC方法");}}}
    }

复制代码

一个简单的控制反转程序例子就实现了。

这样从一定程度上解决了Program与PersonDao耦合的问题,但是实际上并没有完全解决耦合,只是把耦合放到了XML 文件中,通过一个容器在需要的时候把这个依赖关系形成,即把需要的接口实现注入到需要它的类中。我个人认为可以把IoC模式看做是工厂模式的升华,可以把 IoC看作是一个大工厂,只不过这个大工厂里要生成的对象都是在XML文件中给出定义的。

依赖注入
1.控制反转(Inversion of Control)与依赖注入(Dependency Injection)
控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。
IoC是一个很大的概念,可以用不同的方式来实现。其主要实现方式有两种:<1>依赖查找(Dependency Lookup):容器提供回调接口和上下文环境给组件。EJB和Apache Avalon都使用这种方式。<2>依赖注入(Dependency Injection):组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。后者是时下最流行的IoC类型,其又有接口注入(Interface Injection),设值注入(Setter Injection)和构造子注入(Constructor Injection)三种方式。
图1 控制反转概念结构
依赖注入之所以更流行是因为它是一种更可取的方式:让容器全权负责依赖查询,受管组件只需要暴露JavaBean的setter方法或者带参数的构造子或者接口,使容器可以在初始化时组装对象的依赖关系。其与依赖查找方式相比,主要优势为:<1>查找定位操作与应用代码完全无关。<2>不依赖于容器的API,可以很容易地在任何容器以外使用应用对象。<3>不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器。
2.好莱坞原则
IoC体现了好莱坞原则,即“不要打电话过来,我们会打给你”。第一次遇到好莱坞原则是在了解模板方法(Template Mathod)模式的时候,模板方法模式的核心是,基类(抽象类)定义了算法的骨架,而将一些步骤延迟到子类中。
图2 模板方法模式类图
现在来考虑IoC的实现机制,组件定义了整个流程框架,而其中的一些业务逻辑的实现要借助于其他业务对象的加入,它们可以通过两种方式参与到业务流程中,一种是依赖查找(Dependency Lookup),类似与JDNI的实现,通过JNDI来找到相应的业务对象(代码1),另一种是依赖注入,通过IoC容器将业务对象注入到组件中。
3. 依赖查找(Dependency Lookup
下面代码展示了基于JNDI实现的依赖查找机制。
public class MyBusniessObject{private DataSource ds;private MyCollaborator myCollaborator;public MyBusnissObject(){
Context ctx = null;
try{ctx = new InitialContext();ds = (DataSource) ctx.lookup(“java:comp/env/dataSourceName”);myCollaborator =(MyCollaborator) ctx.lookup(“java:comp/env/myCollaboratorName”);}……

代码1依赖查找(Dependency Lookup)代码实现
依赖查找的主要问题是,这段代码必须依赖于JNDI环境,所以它不能在应用服务器之外运行,并且如果要用别的方式取代JNDI来查找资源和协作对象,就必须把JNDI代码抽出来重构到一个策略方法中去。
4. 依赖注入(Dependency Injection
依赖注入的基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。
下面分别演示3中注入机制。
代码2 待注入的业务对象Content.java
package com.zj.ioc.di;public class Content {public void BusniessContent(){System.out.println("do business");}public void AnotherBusniessContent(){System.out.println("do another business");}
}

MyBusniess类展示了一个业务组件,它的实现需要对象Content的注入。代码3,代码4,代码5,6分别演示构造子注入(Constructor Injection),设值注入(Setter Injection)和接口注入(Interface Injection)三种方式。
代码3构造子注入(Constructor Injection)MyBusiness.java
package com.zj.ioc.di.ctor;
import com.zj.ioc.di.Content;public class MyBusiness {private Content myContent;public MyBusiness(Content content) {myContent = content;}public void doBusiness(){myContent.BusniessContent();}public void doAnotherBusiness(){myContent.AnotherBusniessContent();}
}

代码4设值注入(Setter Injection) MyBusiness.java
package com.zj.ioc.di.set;
import com.zj.ioc.di.Content;public class MyBusiness {private Content myContent;public void setContent(Content content) {myContent = content;}public void doBusiness(){myContent.BusniessContent();}public void doAnotherBusiness(){myContent.AnotherBusniessContent();}
}

代码5 设置注入接口InContent.java
package com.zj.ioc.di.iface;
import com.zj.ioc.di.Content;public interface InContent {void createContent(Content content);
}

代码6接口注入(Interface Injection)MyBusiness.java
package com.zj.ioc.di.iface;
import com.zj.ioc.di.Content;public class MyBusiness implements InContent{private Content myContent;public void createContent(Content content) {myContent = content;}public void doBusniess(){myContent.BusniessContent();}public void doAnotherBusniess(){myContent.AnotherBusniessContent();}
}

5.依赖拖拽(Dependency Pull)
最后需要介绍的是依赖拖拽,注入的对象如何与组件发生联系,这个过程就是通过依赖拖拽实现。
代码7 依赖拖拽示例
public static void main(String[] args) throws Exception{
//get the bean factory
BeanFactory factory = getBeanFactory();
MessageRender mr = (MessageRender) factory.getBean(“renderer”);
mr.render();
}

而通常对注入对象的配置可以通过一个xml文件完成。
使用这种方式对对象进行集中管理,使用依赖拖拽与依赖查找本质的区别是,依赖查找是在业务组件代码中进行的,而不是从一个集中的注册处,特定的地点执行。

控制反转---依赖注入理解相关推荐

  1. 那些年搞不懂的高深术语——依赖倒置•控制反转•依赖注入•面向接口编程...

    那些年,空气中仿佛还能闻到汉唐盛世的余韵,因此你决不允许自己的脸上有油光,时刻保持活力.然而,你一定曾为这些"高深术语"感到过困扰--依赖倒置•控制反转•依赖注入•面向接口编程.也 ...

  2. Spring 的控制反转/依赖注入

    第一章 Spring 的控制反转/依赖注入 回顾 增删改查. 课前测: 本章内容 spring:春天 IOC:将创建对象的权力交给 spring 核心容器去控制.工厂模式 BeanFactory: 懒 ...

  3. Spring框架学习笔记(1) ---[spring框架概念 , 初步上手使用Spring , 控制反转 依赖注入初步理解 ]

    spring官网 -->spring官网 spring5.3.12–>spring-framework 在线文档 --> Spring 5.3.12 文章目录 1.Spring概论 ...

  4. 设计模式——控制反转依赖注入

    一.控制反转: 从简单的代码示例入手: /// <summary>/// 邮件服务类/// </summary>public class EmailService{public ...

  5. 【C#|.NET】从控制反转(依赖注入)想到事件注入 (非AOP)

    前文 事件注入的想法是由依赖注入所联想到 依赖注入不算什么吸引人的话题 本篇就不详说了 不过有闲暇时间的机会不妨按照自己的兴趣去摸索.研究一些东西,也是一种乐子. 在抓虫系列里简单的描述一下依赖注入在 ...

  6. 那些年搞不懂的高深术语——依赖倒置•控制反转•依赖注入•面向接口编程【转】...

    那些年,空气中仿佛还能闻到汉唐盛世的余韵,因此你决不允许自己的脸上有油光,时刻保持活力.然而,你一定曾为这些"高深术语"感到过困扰.也许时至今日,你仍对它们一知半解.不过就在今天, ...

  7. 高深术语——依赖倒置•控制反转•依赖注入•面向接口编程

    今天,我将带领你以一种全新的高清视角进入奇妙的编程世界,领略涵泳在这些"高深术语"中的活泼泼的地气,以及翩跹于青萍之末的云水禅心. 高聚合·低耦合 简短:管理好自己(内聚),但是有 ...

  8. 【转】那些年搞不懂的高深术语——依赖倒置•控制反转•依赖注入•面向接口编程

    作者:在好 链接:https://www.zhihu.com/question/31021366/answer/102239756 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  9. 控制反转/依赖注入概念

    控制反转概念 控制反转是影响广泛的设计模式,其主要目的就是为了管理对象之间的关系,为对象之间解除耦合,把对象生命周期的管理和关系的管理这些和对象个体无关的公共任务交给公共容器处理. 控制反转有如下好处 ...

最新文章

  1. h265player开发
  2. 对于注册中心,ZooKeeper、Eureka 哪个更合适?
  3. python爬虫源码下载 视频_Python爬虫下载视频文件部分源码
  4. (chap7 确保WEB安全的HTTPS) HTTP通信问题
  5. php 多维数组怎么去重,php多维数组去重,该如何解决
  6. java深拷贝和浅拷贝介绍
  7. Git 的安装及配置
  8. 雷军:小米有机会重返世界前三;苹果为 Siri 泄露隐私事件致歉;Apache Tomcat 9.0.24 发布 | 极客头条...
  9. 压缩感知及应用 源代码_信言动态|学院成功举办2019年机器学习与压缩感知理论及其应用研讨会...
  10. 线段树 HDU 3397
  11. nginx负载均衡?
  12. Go语言内幕(1):主要概念与项目结构
  13. lunix入侵别人电脑_记录一次Linux的实战入侵过程
  14. 蒸烤一体机哪个品牌好性价比高,盘点国内消费者呼声最高的品牌推荐
  15. cala中隐式转换(implicit conversion)的优先顺序
  16. 100多个新媒体人实用网站
  17. 实现ALOHA协议仿真算法
  18. 市值高达67亿的1元“壳股”海润光伏 谁敢接盘?
  19. Mockito的使用
  20. VSTO | C#快速开发电子签章插件

热门文章

  1. 常州IBMV3700数据恢复成功
  2. Elasticsearch5.3.1+Kibana5.3.1从单机到分布式的安装与使用1
  3. 每日一条linux (1) -find
  4. Javascript学习笔记(三)--变量、作用域和内存问题
  5. Unity3d5.0之后关于游戏音乐的管理
  6. Android布局之LinearLayout
  7. 值得学习的寓言故事和哲理
  8. CSS那些事笔记(一入门)
  9. 甚长基线干涉测量技术(VLBI)基础
  10. java.lang.VerifyError