什么是IoC
IoC是Inversion of Control的缩写,翻译过来为“控制反转”。简单来说,就是将对象的依赖关系交由第三方来控制。在理解这句话之前,我们先来回顾一下IoC的演化。
Ioc前世今生
传统的new class的方式
我们写了一个ChineseSpeaker的类,他有一个SayHello的方法并调用输出控制台:
class Program
{
static void Main(string[] args)
{
ChineseSpeaker chineseSpeaker= new ChineseSpeaker();
chineseSpeaker.SayHello();
}
} public class ChineseSpeaker
{
public void SayHello()
{
Console.WriteLine("你好!!!");
}
}
上面看起来没有任何问题,一切都很好,但是有一天英国演讲者打招呼的话,我们就需要新建了一个BritishSpeaker类:
class Program
{
static void Main(string[] args)
{
//ChineseSpeaker chineseSpeaker = new ChineseSpeaker();
//chineseSpeaker.SayHello(); BritishSpeaker britishSpeaker = new BritishSpeaker();
britishSpeaker.SayHello();
}
} public class BritishSpeaker
{
public void SayHello()
{
Console.WriteLine("Hello!!!");
}
} //ChineseSpeaker 同上面的代码一样
当出现“日本人”、“印度人”时,我们不得不修改和重新编译代码。当程序代码和逻辑不复杂的时候问题不大,但当程序变大的时候程序猿就苦逼了。
Interface方式
因此,我们把代码改成:
public interface ISpeak
{
void SayHello();
} public class BritishSpeaker : ISpeak
{
public void SayHello()
{
Console.WriteLine("Hello!!!");
}
} public class ChineseSpeaker : ISpeak
{
public void SayHello()
{
Console.WriteLine("你好!!!");
}
}
class Program
{
static void Main(string[] args)
{
//ChineseSpeaker chineseSpeaker = new ChineseSpeaker();
//chineseSpeaker.SayHello();
//BritishSpeaker britishSpeaker = new BritishSpeaker();
//britishSpeaker.SayHello(); ISpeak speak; if (args.Length > 0 && args[0] == "Chinese")
{
speak = new ChineseSpeaker();
}
else
{
speak = new BritishSpeaker();
} speak.SayHello();
}
}
这时候我们不知不觉的用到了面向对象六大原则中的依赖倒转原则(DIP),高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口。 好,让我们回到IoC,比较上面的两种写法:
- 传统的写法类在定义的瞬间就已经决定具体的类型,他的流程是从上到下的
- 使用interface的写法是在实例化时才决定类的具体类型,也就是用到的时候才会new(),他的流程是new后面来控制的
这时候我们再来看IoC的意思是控制反转,就能大概理解了。传统的写法流程属于从上到下,而interface写法则是由new()其他的类来决定类的实现,因此控制的流程反转了。
DI是什么
利用interface的方式,可以让类在使用的时候再决定由哪个具体类来实现。那该如何实现这种方式呢?这时就有一个新的名称出现了,就是Dependency Injection(依赖注入),简称DI。DI有三种方式,分别是构造函数注入、属性注入、接口注入
构造函数注入
public class Printer
{
private ISpeak _speak;
public Printer(ISpeak speak)//构造函数注入
{
_speak = speak;
}
} class Program
{
static void Main(string[] args)
{
//ChineseSpeaker chineseSpeaker = new ChineseSpeaker();
//chineseSpeaker.SayHello();
//BritishSpeaker britishSpeaker = new BritishSpeaker();
//britishSpeaker.SayHello(); //ISpeak speak; //if (args.Length > 0 && args[0] == "Chinese")
//{
// speak = new ChineseSpeaker();
//}
//else
//{
// speak = new BritishSpeaker();
//} //speak.SayHello(); Printer print; if (args.Length > 0 && args[0] == "Chinese")
{
print = new Printer(new ChineseSpeaker());
}
else
{
print = new Printer(new BritishSpeaker());
} }
}
属性注入
public class Printer
{
public ISpeak Speaker { get; set; }
} class Program
{
static void Main(string[] args)
{
//ChineseSpeaker chineseSpeaker = new ChineseSpeaker();
//chineseSpeaker.SayHello();
//BritishSpeaker britishSpeaker = new BritishSpeaker();
//britishSpeaker.SayHello(); //ISpeak speak; //if (args.Length > 0 && args[0] == "Chinese")
//{
// speak = new ChineseSpeaker();
//}
//else
//{
// speak = new BritishSpeaker();
//} //speak.SayHello(); Printer print = new Printer();
if (args.Length > 0 && args[0] == "Chinese")
{
print.Speaker = new ChineseSpeaker();
}
else
{
print.Speaker = new BritishSpeaker();
}
}
}
接口注入
//接口注入
public interface IPrint
{
void SetSpeaker(ISpeak speak);
} public class Printer : IPrint
{
private ISpeak _speak;
public void SetSpeaker(ISpeak speak)
{
_speak = speak;
}
} class Program
{
static void Main(string[] args)
{
//ChineseSpeaker chineseSpeaker = new ChineseSpeaker();
//chineseSpeaker.SayHello();
//BritishSpeaker britishSpeaker = new BritishSpeaker();
//britishSpeaker.SayHello(); ISpeak speak; if (args.Length > 0 && args[0] == "Chinese")
{
speak = new ChineseSpeaker();
}
else
{
speak = new BritishSpeaker();
} Printer printer = new Printer();
printer.SetSpeaker(speak);
}
}
IoC与DI的关系
我的理解是IoC是一种理念,DI则是它的具体实现方式
IoC Container
IoC Container帮我们在项目运行时动态的创建实例,它主要功能如下:
- 动态创建、注入依赖对象
- 管理对象生命周期
- 映射依赖关系
IoC Container技术实现的原理就是“反射(Reflection)”。利用反射动态的创建对象,把依赖关系注入到指定对象中。一般常用的注入方式是构造函数注入和属性注入
Service Locator模式
服务定位模式也是IoC理念的一种实现。实现原理:通过ServiceLocator类提供实现IServiceLocator接口的单例,并负责管理已注册实例的创建和访问。通常结合工厂模式来结合使用。
Service Locator与IoC Container都是IoC的具体实现方式。不同的是Service Locator没有提供管理对象生命周期的功能
.NET 平台下的IoC Container框架
Ninject: http://www.ninject.org/
Castle Windsor: http://www.castleproject.org/container/index.html
Autofac: http://code.google.com/p/autofac/
StructureMap: http://docs.structuremap.net/
Unity: http://unity.codeplex.com/
Spring.NET: http://www.springframework.net/
结束语
我在学习IoC过程中,学以致用,自己模仿Nject实现了一个IoC Container框架,可以用FluentAPI和xml配置依赖关系,希望对大家有帮助。项目地址:https://github.com/Khadron/Peace
IoC原理及实现的更多相关文章
-
Java反射机制及IoC原理
一. 反射机制概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义.在java中,只要给定类的名字, 那么就可以通 ...
-
【Spring】Spring IOC原理及源码解析之scope=request、session
一.容器 1. 容器 抛出一个议点:BeanFactory是IOC容器,而ApplicationContex则是Spring容器. 什么是容器?Collection和Container这两个单词都有存 ...
-
IOC原理分析
IOC(inversion of control)控制反转 在我们的程序中,要实现某个功能,我们都会用到两个或两个以上的类来协同完成,那么在一个类中,我们就会要有它的合作类的引用,也就是说这个类依赖于 ...
-
Spring的IOC原理[通俗解释一下]
Spring的IOC原理[通俗解释一下] 1. IoC理论的背景我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑. 图 ...
-
spring原理案例-基本项目搭建 03 创建工程运行测试 spring ioc原理实例示例
下面开始项目的搭建 使用 Java EE - Eclipse 新建一 Dynamic Web Project Target Runtime 选 Apache Tomcat 7.0(不要选 Apache ...
-
Spring之IOC原理及代码详解
一.什么是IOC 引用 Spring 官方原文:This chapter covers the Spring Framework implementation of the Inversion of ...
-
1.IOC原理模拟
Spring两大核心功能,IOC(Inverse of Control) 和 AOP(Aspect-Oriented-Programming) IOC原理模拟: 有这样一个beans.xml: ...
-
【SpringBoot】 理解Spirng中的IOC原理
前言 前文已经介绍了Spring Bean的生命周期,在这个周期内有一个重要的概念就是: IOC容器 大家也知道IOC是Sping 的重要核心之一,那么如何理解它呢,它又是产生什么作用呢?本文就IOC ...
-
Spring IOC原理补充(循环依赖、Bean作用域等)
文章目录 前言 正文 循环依赖 什么是循环依赖? Spring是如何解决循环依赖的? 作用域实现原理以及如何自定义作用域 作用域实现原理 自定义Scope BeanPostProcessor的执行时机 ...
-
Spring IOC 原理深层解析
1 Spring IOC概念认识 1.1 区别IOC与DI 首先我们要知道IOC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spri ...
随机推荐
-
使用swagger作为restful api的doc文档生成
初衷 记得以前写接口,写完后会整理一份API接口文档,而文档的格式如果没有具体要求的话,最终展示的文档则完全决定于开发者的心情.也许多点,也许少点.甚至,接口总是需要适应新需求的,修改了,增加了,这份 ...
-
软件测试之loadrunner学习笔记-02集合点
loadrunner学习笔记-02集合点 集合点函数可以帮助我们生成有效可控的并发操作.虽然在Controller中多用户负载的Vuser是一起开始运行脚本的,但是由于计算机的串行处理机制,脚本的运行 ...
-
unity3d 孤岛求生基础案例
第二个案例,此案例主要实现了第一人称控制器,把移动从世界坐标系转化到人物平面坐标系,通过碰撞器,触发器,光线透射触发器实现交互.实现UI texture记录收集信息,ui texture是更新内容对应 ...
-
Python中如何读取xls中的数据
要想读取EXCEL中的数据,首先得下载xlrd包,地址:https://pypi.python.org/pypi/xlrd 安装方法:下载解压后,利用windows dos命令进入解压目录eg,c ...
-
【转】Github轻松上手6-推荐follow的牛人和值得watch的repo
转自:http://blog.sina.com.cn/s/blog_4b55f6860100zzk5.html Github作为一个social coding 网站,其作用远远超过了一个简单的VCS( ...
-
1044: [HAOI2008]木棍分割 - BZOJ
Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长 ...
-
不同VLAN之间互相通信
前话 我们经常到机房上课,想必对机房后面那层叠的跟DVD一样的机器有印象吧,那些就是交换机. 交换机作用是什么? 我这里度娘一下: 交换机(Switch)意为"开关"是一种用于电( ...
-
打开网页自动弹出qq客户端
新建js后调用即可,打开网站自动弹出qq对话框,若qq为关闭状态则启动qq,之后弹出对话框. document.write("<iframe src='tencent://messag ...
-
关于 ls 命令的一个小小的缺陷
linux 的 ls : ls后边加上要显示的路径时:比方 ls /tmp 它会打印一边 /tmp 下的信息 当ls后边跟上多个同样路径的名字是,它会打印多次同样的信息 比方 ls /tmp /tmp ...
-
windows tcp端口映射或端口转发
windows tcp端口映射或端口转发 windows内部有一个叫netsh的玩意,可以把tcp端口进行映射或转发,可惜不支持udp.举个例子:一台windows有一个80端口,对外可以访问.另有一 ...