一: 为什么要依赖注入

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是一个高阶函数,只接收一个函数,并负责返回需要被注入的依赖。这可以算是延迟依赖类型解析的方案。而之前的模式时第一次实例化依赖符号就会被解析,默认情况下,声明类的时候就需要解析符号。

迈向angularjs2系列(5):依赖注入的更多相关文章

  1. 拥抱.NET Core系列:依赖注入(2)

    上一篇"拥抱.NET Core系列:依赖注入(1)"大体介绍了服务注册.获取和生命周期,这一篇来做一些补充. 由于内容跨度大(.NET Core.ASP.NET Core),所以文 ...

  2. .NET CORE学习笔记系列(2)——依赖注入[7]: .NET Core DI框架[服务注册]

    原文https://www.cnblogs.com/artech/p/net-core-di-07.html 包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IS ...

  3. .NET CORE学习笔记系列(2)——依赖注入[6]: .NET Core DI框架[编程体验]

    原文https://www.cnblogs.com/artech/p/net-core-di-06.html 毫不夸张地说,整个ASP.NET Core框架是建立在一个依赖注入框架之上的,它在应用启动 ...

  4. .NET CORE学习笔记系列(2)——依赖注入[5]: 创建一个简易版的DI框架[下篇]

    为了让读者朋友们能够对.NET Core DI框架的实现原理具有一个深刻而认识,我们采用与之类似的设计构架了一个名为Cat的DI框架.在上篇中我们介绍了Cat的基本编程模式,接下来我们就来聊聊Cat的 ...

  5. .NET CORE学习笔记系列(2)——依赖注入[4]: 创建一个简易版的DI框架[上篇]

    原文https://www.cnblogs.com/artech/p/net-core-di-04.html 本系列文章旨在剖析.NET Core的依赖注入框架的实现原理,到目前为止我们通过三篇文章从 ...

  6. .NET CORE学习笔记系列(2)——依赖注入【3】依赖注入模式

    原文:https://www.cnblogs.com/artech/p/net-core-di-03.html IoC主要体现了这样一种设计思想:通过将一组通用流程的控制权从应用转移到框架中以实现对流 ...

  7. .NET CORE学习笔记系列(2)——依赖注入【2】基于IoC的设计模式

    原文:https://www.cnblogs.com/artech/p/net-core-di-02.html 正如我们在<控制反转>提到过的,很多人将IoC理解为一种“面向对象的设计模式 ...

  8. .NET CORE学习笔记系列(2)——依赖注入【1】控制反转IOC

    原文:https://www.cnblogs.com/artech/p/net-core-di-01.html 一.流程控制的反转 IoC的全名Inverse of Control,翻译成中文就是“控 ...

  9. 迈向angularjs2系列(1):typescript指南

    typescript指南 前言 typescript是angularjs2推荐使用的脚本语言.它由微软2012年首次发布. 一.    typescript和javascript的区别 1.从遵循的规 ...

随机推荐

  1. 51nod_1831: 小C的游戏(Bash博弈 找规律)

    题目链接 此类博弈不需要考虑sg函数,只需要确定必胜态和必败态,解题思路一般为打败先打表找规律,而后找规律给出统一的公式.打表方式:给定初始条件(此题中为ok[0]=ok[1]=0),然后从低到高枚举 ...

  2. (转)ORACLE中SID和SERVICE_NAME的区别

    背景:之前一直分不清plsql和程序中配置文件url之间的连接,想当然的认为service_name 和jdburl后面的实例相对应,直到出错的这一天,通过这篇博客,彻底扫除了盲点. 1 问题 1.1 ...

  3. [js] 小谈 export (没总结完)

    作用 导出变量/类 等等 用法 index.js 文件 export default name 仅导出一个变量 import name from './index.js' index.js 文件 ex ...

  4. [BZOJ 4325][NOIP 2015] 斗地主

    一道防AK好题 4325: NOIP2015 斗地主 Time Limit: 30 Sec  Memory Limit: 1024 MBSubmit: 820  Solved: 560[Submit] ...

  5. JVM学习笔记二:垃圾收集算法

    垃圾回收要解决的问题: 哪些内存需要回收? 线程私有区域不需要回收,如PC.Stack.Native Stack:Java 堆和方法区需要 什么时候回收? 以后的文章解答 如何回收? 首先进行对象存活 ...

  6. 移动端touch事件封装

    <meta charset="utf-8"><meta name="viewport" content="width=device- ...

  7. 在同一个sql语句中,统计不同条件的Count数量

    前几天帮同事优化了个SQL,原写法使用多个子查询这里不再重现了,大家都遇到过这样一种情况,在项目后期的维护中, 修改别人的SQL代码,超过30行的语句,多层子查询,读起来很坑,时间久的项目伴随着人员的 ...

  8. C#设计模式(0)-认识设计模式

    简介 世界上本没有路,走的人多了也就成了路:世界上本来没有设计模式.用的人多了,也就成了设计模式.所以,我们不是严格按照它的定义去执行,可以根据自己的实际场景.需求去变通.领悟了其中的思想,实现属于自 ...

  9. No simulation input file assignm…

    QuartusII中仿真时出现No simulation input file assignment specified on simulator page of the settings dialo ...

  10. list集合为空或为null的区别

    简述 判断一个list集合是否为空,我们的惯性思维是判断list是否等于null即可,但是在Java中,list集合为空还是为null,这是两码事. 新建一个list对象,默认值是空,而非null: ...