zoukankan      html  css  js  c++  java
  • 迈向angularjs2系列(5):依赖注入

    一: 为什么要依赖注入

    1.构造器引入依赖

    假设一个类Car类依赖于Engine(引擎)类、Transition(变速箱)类,可使用构造器来完成。

    //类似如下代码
    class Engine{}
     class Transmission{}
     class Car {
      engine;
      transmisssion;
      constructor(){
        this.engine=new Engine();
        this.transmisssion=new Transmission();
      }

    构造函数创建似乎简洁明了,但是不灵活。Car类和其他两个类耦合度高,每当创建Car类,也会创建Engine类和Transmission类,它们的可测试性分别受到影响。

    2.引入依赖注入

    有后续的完善哦,这里只是简单的重构了一下。

    class Engine{}
    class Transmission{}
     @Injectable
    //仅仅改动的地方
     class Car {
      engine;
      transmisssion;
      constructor(engine:Engine,transmission:Transmisson){
        this.engine=engine;
        this.transmisssion=transmission;
      }
     }

    二: 配置注射器

    在angular2中,使用注射器实现依赖注入机制。

    完整的代码injector.ts:

    import "reflect-metadata";
    //引入 reflect-metadata 库来使用元数据反射 API:
    import {
      Injector,Inject,Injectable,OpaqueToken,provide,ReflectiveInjector
    } from "@angular/core";
    const BUFFER_SIZE=new OpaqueToken("buffer-size");
    //token常量,在整个应用里唯一、不可重复定义的值。
    class Buffer{
      //@Inject装饰器接收依赖对象的token
      constructor(@Inject(BUFFER_SIZE) private size:Number){
        console.log(this.size);
      }
      //Buffer类接收依赖参数size
    }
    //使用生成的元数据解析依赖关系
    @Injectable()
    class Socket {
      constructor(private buffer:Buffer){}
    }
    
    const injector: Injector =
      ReflectiveInjector.resolveAndCreate([
        {provide: BUFFER_SIZE, useValue: '42'},
        Buffer,
        Socket
        ]);
    //初始化注射器
    injector.get(Socket);

    1.导入

    import "reflect-metadata";
    import {
      Injector,Inject,Injectable,OpaqueToken,provide,ReflectiveInjector
    } from "@angular/core";

    2.token的定义和Inject装饰器接收token

    const BUFFER_SIZE=new OpaqueToken("buffer-size");
    BUFFER_SIZE这个常量,可以看做整个应用中唯一、不可重复定义的值。

    3.使用生成的元数据解析依赖关系

    @Injectable()
    class Socket {
      constructor(private buffer:Buffer){}
    }
    Socket类用@Injectable()进行装饰,强制typescript编译器生成额外的元数据,用以描述指定的类能够注入哪些类型的依赖。这有点像angular1代码的压缩,一定要写成数组形式,以便压缩后的代码能够知道注入的是什么参数。
    所以,如果省略掉装饰器,angular2的DI机制就不知道哪些符号对应的依赖关系需要进行注入了。
    class Socket {
      constructor(@Inject(Buffer)private buffer:Buffer){}
    }
    //与上面代码等价哦

    4.初始化注射器

    const injector: Injector =
      ReflectiveInjector.resolveAndCreate([
        {provide: BUFFER_SIZE, useValue: '42'},
        Buffer,
        Socket
        ]);
    //使用resolveAndCreate静态方法创建Injector类的实例

    resolveAndCreate是一个工厂方法,可接收一个provider数组作为参数,返回值是一个新的Injector实例。

    resolvede的意思是provider将会执行一次解析过程。

    5.前向引用

    如果Socket类定义在Buffer类之前呢,由于Js代码的从上往下执行,会报错说Buffer没有定义undefined。

    那么除了用正确的顺序来定义它们之外,还有一种解决方案,前向引用。

    import {forwardRef} from"@angular/core"
    @Injectable()
    class Socket {
      constructor(@Inject(forwardRef(()=>Buffer)) private buffer:Buffer){}
    }
    //前向引用唯一要做的就是使用@Inject装饰器,并把forwardRef函数的执行结果传给它。
    forwardRef是一个高阶函数,只接收一个函数,并负责返回需要被注入的依赖。这可以算是延迟依赖类型解析的方案。而之前的模式时第一次实例化依赖符号就会被解析,默认情况下,声明类的时候就需要解析符号。

  • 相关阅读:
    编译原理第一次作业
    【码制】关于原码,反码,补码的一些笔记和理解
    输出1到50以内的所有素数【C】
    方法和数组
    if条件判断和switch,for do while
    变量
    全选,删除,添加
    java基础
    二级联
    轮播图
  • 原文地址:https://www.cnblogs.com/chenmeng2062/p/7106586.html
Copyright © 2011-2022 走看看