• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >JavaScript > 详解Angular 4.x Injector

详解Angular 4.x Injector

作者:semlinker 字体:[增加 减小] 来源:互联网 时间:2017-05-11

semlinker通过本文主要向大家介绍了angular injector,unity 4.x pro patch,英特尔 4.x,spring 4.x,express 4.x等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

在介绍 Angular Injector (注入器) 之前,我们先要了解 Dependency Injection,即依赖注入的概念。

依赖注入允许程序设计遵从依赖倒置原则 (简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户端与实现模块间的耦合) 调用者只需知道服务的接口,具体服务的查找和创建由注入器 (Injector) 负责处理并提供给调用者,这样就分离了服务和调用者的依赖,符合低耦合的程序设计原则。

从上述的内容可知,依赖注入中包含三种角色:调用者、服务和注入器 (Injector)。现在我们开始介绍 Injector,在 Angular 中 Injector (注入器) 用来管理服务对象的创建和获取。接下来我们先来看一下 Injector 抽象类:

Injector 抽象类

// angular2\packages\core\src\di\injector.ts
export abstract class Injector {
 static THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
 static NULL: Injector = new _NullInjector();

 /**
 * 用于根据给定的Token从注入器中获取相应的对象。
 * 如果没有找到相应的对象,将返回notFoundValue设置的值。若notFoundValue的值与
 * _THROW_IF_NOT_FOUND相等,则会抛出异常。
 */
 abstract get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T): T;
}

const _THROW_IF_NOT_FOUND = new Object();
</div>

Injector 抽象类中定义了一个 get() 抽象方法,该方法用于根据给定的 Token 从注入器中获取相应的对象,每个Injector 抽象类的子类都必须实现该方法。在 Angular 中常见的 Injector 抽象类子类有:

  1. _NullInjector
  2. ReflectiveInjector

下面我们来依次介绍它们:

_NullInjector 类

_NullInjector 类的实例用于表示空的注入器。

// angular2\packages\core\src\di\injector.ts
class _NullInjector implements Injector {
 get(token: any, notFoundValue: any = _THROW_IF_NOT_FOUND): any {
 if (notFoundValue === _THROW_IF_NOT_FOUND) {
  throw new Error(`No provider for ${stringify(token)}!`);
 }
 return notFoundValue;
 }
}
</div>

ReflectiveInjector 抽象类

ReflectiveInjector 表示一个依赖注入容器,用于实例化对象和解析依赖。

ReflectiveInjector 使用示例

@Injectable()
class Engine {}

@Injectable()
class Car {
 constructor(public engine:Engine) {}
}

var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]);
var car = injector.get(Car);
expect(car instanceof Car).toBe(true);
expect(car.engine instanceof Engine).toBe(true);
</div>

上面示例中,我们通过调用 ReflectiveInjector 抽象类的 resolveAndCreate() 方法,创建注入器。然后通过调用注入器的 get() 方法,获取 Token 对应的对象。该抽象类除了 resolveAndCreate() 静态方法外,还含有以下静态方法:

  1. resolve() - 解析 Provider 列表为 ResolvedReflectiveProvider 列表
  2. fromResolvedProviders() - 基于 ResolvedReflectiveProvider 列表创建 ReflectiveInjector 对象

接下来我们来分析上述的静态方法:

resolveAndCreate()

static resolveAndCreate(providers: Provider[], parent?: Injector): ReflectiveInjector {
 const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
 return ReflectiveInjector.fromResolvedProviders(ResolvedReflectiveProviders, parent);
}
</div>

从上面代码中,我们可以看出 resolveAndCreate() 方法内部是通过调用 ReflectiveInjector.resolve() 方法和 ReflectiveInjector.fromResolvedProviders() 方法来创建 ReflectiveInjector 对象。

resolve()

该方法用于把 Provider 数组解析为 ResolvedReflectiveProvider 数组。

static resolve(providers: Provider[]): ResolvedReflectiveProvider[] {
 return resolveReflectiveProviders(providers);
}
</div>

resolve() 使用示例

@Injectable()
class Engine {}

@Injectable()
class Car {
 constructor(public engine:Engine) {}
}

var providers = ReflectiveInjector.resolve([Car, [[Engine]]]);
expect(providers.length).toEqual(2);

expect(providers[0] instanceof ResolvedReflectiveProvider).toBe(true);
expect(providers[0].key.displayName).toBe("Car");
expect(providers[1].key.displayName).toBe("Engine");
</div>

resolve() 解析图示

 

Provider 类型

export type Provider =
 TypeProvider | ValueProvider | ClassProvider | ExistingProvider | FactoryProvider | any[];

// ApiService
export interface TypeProvider extends Type<any> {}

// { provide: ApiService, useClass: ApiService } 
export interface ClassProvider {
 // 用于设置与依赖对象关联的Token值,Token值可能是Type、InjectionToken、OpaqueToken的实例或字符串
 provide: any; 
 useClass: Type<any>;
 // 用于标识是否multiple providers,若是multiple类型,则返回与Token关联的依赖对象列表
 multi?: boolean; 
}
 
// { provide: 'API_URL', useValue: 'http://my.api.com/v1' }
export interface ValueProvider {
 provide: any;
 useValue: any;
 multi?: boolean;
}
 
// { provide: 'ApiServiceAlias', useExisting: ApiService } 
export interface ExistingProvider {
 provide: any;
 useExisting: any;
 multi?: boolean;
}
 
// { provide: APP_INITIALIZER, useFactory: configFactory, deps: [AppConfig], multi: true }
export interface FactoryProvider {
 provide: any;
 useFactory: Function;
 deps?: any[]; // 用于设置工厂函数的依赖对象
 multi?: boolean;
}

</div>

ResolvedReflectiveProvider 接口

export interface ResolvedReflectiveProvider {
 // 唯一的对象用来从ReflectiveInjector中获取对象
 key: ReflectiveKey;
 // 工厂函数用于创建key相关的依赖对象 
 resolvedFactories: ResolvedReflectiveFactory[];
 // 标识当前的provider是否为multi-provider
 multiProvider: boolean;
}
</div>

ResolvedReflectiveFactory 类

export class ResolvedReflectiveFactory {
 constructor(
  public factory: Function,
  public dependencies: ReflectiveDependency[]) {}
}
</div>

ReflectiveDependency 类

export class ReflectiveDependency {
 constructor(
  public key: ReflectiveKey, 
  public optional: boolean, 
  public visibility: Self|SkipSelf|null) {}

 static fromKey(key: ReflectiveKey): ReflectiveDependency {
 return new ReflectiveDependency(key, false, null);
 }
}
</div>

ReflectiveKey 类

ReflectiveKey 对象中包含两个属性:系统范围内唯一的id 和 token。系统范围内唯一的id,允许注入器以更高效的方式存储已创建的对象。另外我们不能手动的创建 ReflectiveKey,当 ReflectiveInjector 对象解析 providers 的时候会自动创建 ReflectiveKey 对象。

export class ReflectiveKey {
 constructor(public token: Object, public id: number) {
 if (!token) {
  throw new Error('Token must be defined!');
 }
 }
 
 // 返回序列化的token
 get displayName(): string { return stringify(this.token); }

 // 获取token对应的ReflectiveKey
 static get(token: Object): ReflectiveKey {
 return _globalKeyRegistry.get(resolveForwardRef(token));
 }

 // 获取系统中已注册ReflectiveKey的个数
 static get numberOfKeys(): number { return _globalKeyRegistry.numberOfKeys; }
}

const _globalKeyRegistry = new KeyRegistry(); // 创建Key仓



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 详解Angular 4.x Injector

相关文章

  • 2017-05-11Node.js 中exports 和 module.exports 的区别
  • 2017-05-11AngularJS constant和value区别详解
  • 2017-05-11js实现贪吃蛇小游戏(容易理解)
  • 2017-05-11使用jquery判断一个元素是否含有一个指定的类(class)实例
  • 2017-05-11微信小程序开发之Tabbar实例详解
  • 2017-05-11用jQuery实现优酷首页轮播图
  • 2017-05-11bootstrap vue.js实现tab效果
  • 2017-05-11Node.js中文件操作模块File System的详细介绍
  • 2017-05-11移动端触屏幻灯片图片切换插件idangerous swiper.js
  • 2017-05-11BootStrap的select2既可以查询又可以输入的实现代码

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • jquery 实现复选框的全选操作实例代码
    • JS控件bootstrap suggest plugin使用方法详解
    • Bootstrap缩略图的创建方法
    • 使用jQuery ajaxupload插件实现无刷新上传文件
    • Canvas + JavaScript 制作图片粒子效果
    • 全面总结Javascript对数组对象的各种操作
    • 数据结构 Map—ES6学习笔记
    • jQuery插件扩展操作入门示例
    • jq给页面添加覆盖层遮罩的实例
    • HTML5 js实现拖拉上传文件功能

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有