IoC原理及实现

什么是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 同上面的代码一样

到目前为止,代码已经暴露出设计原则中要避免的问题:松耦合(loose coupling)。程序中非常依赖实际的class,这导致了:

当出现“日本人”、“印度人”时,我们不得不修改和重新编译代码。当程序代码和逻辑不复杂的时候问题不大,但当程序变大的时候程序猿就苦逼了。

Interface方式

为了避免这种直接依赖关系,我们需要把对象或行为抽象出来一个东西,叫做接口(interface)。它就像电脑中的usb插口,无论是优盘还是鼠标只要插头是usb的我就能使用,从而屏蔽了复杂性。

因此,我们把代码改成:

        public interface ISpeak
        {
            void SayHello();
        }

        public class BritishSpeaker : ISpeak
        {
            public void SayHello()
            {
                Console.WriteLine("Hello!!!");
            }
        }

        public class ChineseSpeaker : ISpeak
        {
            public void SayHello()
            {
                Console.WriteLine("你好!!!");
            }
        }

因为我们现在把类的实现和功能拆出来了,所以我们可以让客户端动态的来选择谁SayHello

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

时间: 2024-11-05 22:50:13

IoC原理及实现的相关文章

Java反射机制及IoC原理

一. 反射机制概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高! 类中有什么信息,利用反射机制就能可以获得什么信息,不过前提是得知道类的名字. 二. 反射机制的作用 在运行时判断任意

Spring IOC原理(初级版)

Spring框架是由于软件开发的复杂性而创建的.Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的用途不仅仅限于服务器端的开发.从简单性.可测试性和松耦合性的角度而言,绝大部分Java应用都可以从Spring中受益. ------------------------------------------------------------↑ 以上都是废话,我也不懂 ↑   ↓ 下面是整体架构,可以略过 ↓ ----------------------

【Spring】Spring IOC原理及源码解析之scope=request、session

一.容器 1. 容器 抛出一个议点:BeanFactory是IOC容器,而ApplicationContex则是Spring容器. 什么是容器?Collection和Container这两个单词都有存放什么东西的意思,但是放在程序猿的世界,却注定是千差万别.Collection,集合,存放obj instanceof Class为true的一类对象,重点在于存放:Container,容器,可以存放各种各样的obj,但不仅仅是存放,他被称为容器,更重要的是他能管理存放对象的生命周期和依赖. 容器:

Spring——IoC原理

一.概念 IoC是Inversion of Control的缩写,有的翻译成"控制反转",还有翻译为"控制反向"或者"控制倒置". 二.什么是IoC IoC就是IoC,不是什么技术,与GoF一样,是一种设计模式.在Spring中控制反转是Spring框架的核心,其原理是基于OO设计原则的:Don't call us,we'll call you(别来找我,我会来找你的).也就是说,所有组件都是被动的,所有的组件初始化和调用都由容器负责.组件处在一

1.IOC原理模拟

Spring两大核心功能,IOC(Inverse  of  Control)  和 AOP(Aspect-Oriented-Programming) IOC原理模拟: 有这样一个beans.xml: 1 <beans> 2 <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" /> 3 <bean id="userService" class="com.bj

IOC原理分析

IOC(inversion of control)控制反转 在我们的程序中,要实现某个功能,我们都会用到两个或两个以上的类来协同完成,那么在一个类中,我们就会要有它的合作类的引用,也就是说这个类依赖于别的类,这个合作类的获取,将会有一下几种不同的情况 依赖获取的三种方式: Java代码 情况1.自己生成 Class person{ Eat(){ Apple a=new Apple(); } } 第一种方式:在person的eat()方法里就把吃的水果写死,从开始就创建对象, 缺点 :1.Pers

Java反射及 IoC原理、内省机制

JAVA反射及IoC原理.JAVA内省 1. 反射 反射是框架设计的灵魂,使用前提:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码文件). 1.1 反射概述 主要指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. Java反射机制:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性. 1.2 反射机制的作用 在运行时判断任

好程序员Java干货分享Spring框架之IOC原理

好程序员Java干货分享Spring框架之IOC原理,前言:Spring框架是我们进行企业级开发的最常用框架,本章我们将了解Spring框架,并学习Spring的IOC特性以及IOC的实现原理:注解和反射. Spring框架简介 Spring是一种轻量级的控制反转(IOC)和面向切面编程(AOP)的容器框架,能够为企业级开发提供一站式服务. Spring的优点有 1.方便解耦,简化开发 通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度

【SpringBoot】 理解Spirng中的IOC原理

前言 前文已经介绍了Spring Bean的生命周期,在这个周期内有一个重要的概念就是: IOC容器 大家也知道IOC是Sping 的重要核心之一,那么如何理解它呢,它又是产生什么作用呢?本文就IOC原理进行简要阐述. IOC定义 IoC 全称为 Inversion of Control,翻译为 “控制反转”,它还有一个别名为 DI(Dependency Injection),即依赖注入. DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的

Spring源码:IOC原理解析(一)

版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! IOC(Inversion of Control),即控制反转,意思是将对象的创建和依赖关系交给第三方容器处理,我们要用的时候告诉容器我们需要什么然后直接去拿就行了.举个例子,我们有一个工厂,它生产各种产品,当你需要某个产品,比如你需要一辆汽车,你就告诉工厂你需要一辆汽车,工厂就会直接返回给你一辆汽车,而不需要你自己通过付出劳动来得到这辆汽车,你也不用关心工厂是如何生产这辆汽车.对应到我们的程序中就是,IOC容器会帮我们创建和管理对象