IOC and DI essential understanding

IoC

 

IoC: Inversion of Control, the inversion of control, the transfer of control from the application to the framework (such as the IoC container), is a common feature of the framework
 

 

1. Why do I need an IoC container?
1.1. The application actively controls the instantiation and dependency assembly of objects 
Java code   Favorite code
  1. A a = new AImpl();  
  2. B b = new BImpl();  
  3. a.setB(b);  
Essence: object creation, active instantiation, direct access to dependencies, active assembly 
Disadvantage: Replacing the implementation requires recompiling the source code
           Hard to replace implementations, hard to test
           Coupling instance producers and instance consumers 
 
Java code   Favorite code
  1. A a = AFactory.createA();  
  2. B b = BFactory.createB();  
  3. a.setB(b);  
 
Essence: object creation, passive instantiation, indirect acquisition of dependencies, active assembly (simple factory) 
Disadvantage: Replacing the implementation requires recompiling the source code
           Hard to replace implementations, hard to test
 
 
Java code   Favorite code
  1. A a = Factory.create(“a”);  
  2. B b = Factory.create(“b”);  
  3. a.setB(b);   
 
  <!—Configuration.properties-->
Xml code   Favorite code
  1. a=AImpl  
  2. b=BImpl  
 
Essence: object creation, passive instantiation, indirect acquisition of dependencies, active assembly
        (factory + reflection + properties configuration file,
           Service Locator, Registry) 
Disadvantage: Redundant dependency assembly logic
 
 
I want to directly:
    //返回装配好的a
Java代码   Favorite code
  1. A a = Factory.create(“a”);   
 
              
1.2、可配置通用工厂:工厂主动控制,应用程序被动接受,控制权从应用程序转移到工厂
Java代码   Favorite code
  1. //返回装配好的a   
  2. A a = Factory.create(“a”);  
   <!—配置文件-->
Java代码   Favorite code
  1. <bean id=“a” class=“AImpl”>  
  2.     <property name=“b” ref=“b”/>  
  3. </bean>  
  4. <bean id=“b” class=“BImpl”/>  
 本质:创建对象和装配对象, 
          被动实例化,被动接受依赖,被动装配
        (工厂+反射+xml配置文件)
缺点:不通用
 
步骤:
1、读取配置文件根据配置文件通过反射
创建AImpl
2、发现A需要一个类型为B的属性b
3、到工厂中找名为b的对象,发现没有,读取
配置文件通过反射创建BImpl
4、将b对象装配到a对象的b属性上
【组件的配置与使用分离开(解耦、更改实现无需修改源代码、易于更好实现) 】
 
1.3、 IoC(控制反转)容器:容器主动控制
Java代码   Favorite code
  1. //返回装配好的a   
  2. A a = ApplicationContext.getBean(“a”);  
 <!—配置文件-->
Java代码   Favorite code
  1. <bean id=“a” class=“AImpl”>  
  2.     <property name=“b” ref=“b”/>  
  3. </bean>  
  4. <bean id=“b” class=“BImpl”/>  
 
本质:创建对象和装配对象、管理对象生命周期
          被动实例化,被动接受依赖,被动装配
        (工厂+反射+xml配置文件)
通用 


 
 
IoC容器:实现了IoC思想的容器就是IoC容器
 
2、IoC容器特点
【1】无需主动new对象;而是描述对象应该如何被创建即可
          IoC容器帮你创建,即被动实例化;
【2】不需要主动装配对象之间的依赖关系,而是描述需要哪个服务(组件),
         IoC容器会帮你装配(即负责将它们关联在一起),被动接受装配;
【3】主动变被动,好莱坞法则:别打电话给我们,我们会打给你;
【4】迪米特法则(最少知识原则):不知道依赖的具体实现,只知道需要提供某类服务的对象(面向抽象编程),松散耦合,一个对象应当对其他对象有尽可能少的了解,不和陌生人(实现)说话
【5】IoC是一种让服务消费者不直接依赖于服务提供者的组件设计方式,是一种减少类与类之间依赖的设计原则。
 
3、理解IoC容器问题关键:控制的哪些方面被反转了?
1、谁控制谁?为什么叫反转? ------  IoC容器控制,而以前是应用程序控制,所以叫反转 
2、控制什么?               ------  控制应用程序所需要的资源(对象、文件 ……
3、为什么控制?             ------  解耦组件之间的关系 
4、控制的哪些方面被反转了? ------  程序的控制权发生了反转:从应用程序转移到了IoC容器。 
 
思考:
    1: IoC/DI等同于工厂吗?
    2: IoC/DI跟以前的方式有什么不一样?
领会: 主从换位的思想

 
 
4、实现了IoC思想的容器就是轻量级容器吗?
如果仅仅因为使用了控制反转就认为这些轻量级容器与众不同,就好象在说我的轿车与众不同因为它有四个轮子? 
 
容器:提供组件运行环境,管理组件声明周期(不管组件如何创建的以及组件之间关系如何装配的);
 
IoC容器不仅仅具有容器的功能,而且还具有一些其他特性---如依赖装配
             
控制反转概念太广泛,让人迷惑,后来 Martin Fowler 提出依赖注入概念
Martin Fowler  Inversion of Control Containers and the Dependency Injection pattern  
http://martinfowler.com/articles/injection.html
 
 
DI
 
2、什么是DI
 
DI:依赖注入(Dependency Injection) :用一个单独的对象(装配器)来装配对象之间的依赖关系 。


 
2、理解DI问题关键
谁依赖于谁?           -------    应用程序依赖于IoC容器
为什么需要依赖?        -------    应用程序依赖于IoC容器装配类之间的关系
依赖什么东西?          -------    依赖了IoC容器的装配功能
谁注入于谁?            -------    IoC容器注入应用程序
注入什么东西?          -------    注入应用程序需要的资源(类之间的关系)
 
更能描述容器其特点的名字 ——“依赖注入”(Dependency Injection)
IoC容器应该具有依赖注入功能,因此也可以叫DI容器 
 
3、DI优点
    【1】帮你看清组件之间的依赖关系,只需要观察依赖注入的机制(setter/构造器),就可以掌握整个依赖(类与类之间的关系)。
    【2】组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
    【3】依赖注入的目标并非为软件系统带来更多的功能,而是为了提升组件重用的概率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不用关心具体的资源来自何处、由谁实现。
 
使用DI限制:组件和装配器(IoC容器)之间不会有依赖关系,因此组件无法从装配器那里获得更多服务,只能获得配置信息中所提供的那些。 
 
4、实现方式
   1、构造器注入
   2、setter注入
   3、接口注入:在接口中定义需要注入的信息,并通过接口完成注入
       @Autowired
       public void prepare(MovieCatalog movieCatalog,
           CustomerPreferenceDao customerPreferenceDao) {
           this.movieCatalog = movieCatalog;
           this.customerPreferenceDao = customerPreferenceDao;
       }
 
 
 
使用IoC/DI容器开发需要改变的思路
1、应用程序不主动创建对象,但要描述创建它们的方式。
2、在应用程序代码中不直接进行服务的装配,但要配置文件中描述哪一个组件需要哪一项服务。容器负责将这些装配在一起。
 
The principle is based on The Hollywood Principle of OO design principles: Don't call us, we'll call you (don't call me, I'll call you). That is, all components are passive (Passive), and all component initialization and assembly are handled by the container. Components are in a container, which is managed by the container.
 
IoC container functions: instantiate, initialize components, assemble component dependencies, and be responsible for component life cycle management.
 
Nature:
      IoC: transfer of control, from the application to the framework;
      IoC/DI container: The application actively instantiates the object to passively wait for the object (passive instantiation);
      DI: The relationship between components assembled by a special assembler;
      IoC/DI container: The application actively assembles the object's dependencies, and the application passively accepts dependencies
 

For details on the relationship between IoC/DI and DIP, see  http://www.iteye.com/topic/1122310?page=5#2335746

 

IoC/DI and the Law of Demeter see http://www.iteye.com/topic/1122310?page=5#2335748

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326144191&siteId=291194637