在介绍 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"htmlcode">// 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; } }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);上面示例中,我们通过调用 ReflectiveInjector 抽象类的
resolveAndCreate()
方法,创建注入器。然后通过调用注入器的get()
方法,获取 Token 对应的对象。该抽象类除了resolveAndCreate()
静态方法外,还含有以下静态方法:
- resolve() - 解析 Provider 列表为 ResolvedReflectiveProvider 列表
- fromResolvedProviders() - 基于 ResolvedReflectiveProvider 列表创建 ReflectiveInjector 对象
接下来我们来分析上述的静态方法:
resolveAndCreate()
static resolveAndCreate(providers: Provider[], parent"htmlcode">static resolve(providers: Provider[]): ResolvedReflectiveProvider[] { return resolveReflectiveProviders(providers); }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");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"htmlcode">export interface ResolvedReflectiveProvider { // 唯一的对象用来从ReflectiveInjector中获取对象 key: ReflectiveKey; // 工厂函数用于创建key相关的依赖对象 resolvedFactories: ResolvedReflectiveFactory[]; // 标识当前的provider是否为multi-provider multiProvider: boolean; }ResolvedReflectiveFactory 类
export class ResolvedReflectiveFactory { constructor( public factory: Function, public dependencies: ReflectiveDependency[]) {} }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); } }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仓库 export class KeyRegistry { private _allKeys = new Map<Object, ReflectiveKey>(); /** * 若token是ReflectiveKey类的实例,则直接返回。若_allKeys对象中包含token属性 * 则返回token对应的ReflectiveKey对象。否则创建一个新的ReflectiveKey对象,并 * 保存到_allKeys对象中 */ get(token: Object): ReflectiveKey { if (token instanceof ReflectiveKey) return token; if (this._allKeys.has(token)) { return this._allKeys.get(token) !; } const newKey = new ReflectiveKey(token, ReflectiveKey.numberOfKeys); this._allKeys.set(token, newKey); return newKey; } // 获取已保存ReflectiveKey的个数 get numberOfKeys(): number { return this._allKeys.size; } }分析完
resolve()
方法的输入参数和返回类型,我们来看一下该方法内部的具体实现:export function resolveReflectiveProviders(providers: Provider[]) : ResolvedReflectiveProvider[] { const normalized = _normalizeProviders(providers, []); // 步骤一 const resolved = normalized.map(resolveReflectiveProvider); // 步骤二 const resolvedProviderMap = mergeResolvedReflectiveProviders(resolved, new Map()); // 步骤三 return Array.from(resolvedProviderMap.values()); // 步骤四 }步骤一 —— 规范化Provider
const normalized = _normalizeProviders(providers, []); // 规范化Providers function _normalizeProviders(providers: Provider[], res: Provider[]): Provider[] { providers.forEach(b => { // providers: [Type] => providers: [{provide: Type, useClass: Type }] if (b instanceof Type) { res.push({provide: b, useClass: b}); } else if (b && typeof b == 'object' && (b as any).provide !== undefined) { res.push(b as NormalizedProvider); } else if (b instanceof Array) { // 若b是数组,则递归调用_normalizeProviders()方法 _normalizeProviders(b, res); } else { throw invalidProviderError(b); } }); return res; } interface NormalizedProvider extends TypeProvider, ValueProvider, ClassProvider, ExistingProvider, FactoryProvider {}步骤二 —— 转化NormalizedProvider为ResolvedReflectiveProvider
const resolved = normalized.map(resolveReflectiveProvider); // 解析NormalizedProvider为ResolvedReflectiveProvider function resolveReflectiveProvider(provider: NormalizedProvider): ResolvedReflectiveProvider { return new ResolvedReflectiveProvider_( ReflectiveKey.get(provider.provide), [resolveReflectiveFactory(provider)], provider.multi || false); } // 用于创建已解析的Provider实例 export class ResolvedReflectiveProvider_ implements ResolvedReflectiveProvider { constructor( public key: ReflectiveKey, public resolvedFactories: ResolvedReflectiveFactory[], public multiProvider: boolean) {} get resolvedFactory(): ResolvedReflectiveFactory { return this.resolvedFactories[0]; } } // 解析NormalizedProvider对象,创建ResolvedReflectiveFactory对象 function resolveReflectiveFactory(provider: NormalizedProvider): ResolvedReflectiveFactory { let factoryFn: Function; let resolvedDeps: ReflectiveDependency[]; if (provider.useClass) { // { provide: ApiService, useClass: ApiService } const useClass = resolveForwardRef(provider.useClass); factoryFn = reflector.factory(useClass); resolvedDeps = _dependenciesFor(useClass); } else if (provider.useExisting) { // { provide: 'ApiServiceAlias', useExisting: ApiService } factoryFn = (aliasInstance: any) => aliasInstance; resolvedDeps = [ReflectiveDependency.fromKey(ReflectiveKey.get(provider.useExisting))]; } else if (provider.useFactory) { // { provide: APP_INITIALIZER, useFactory: configFactory, deps: [AppConfig], // multi: true } factoryFn = provider.useFactory; resolvedDeps = constructDependencies(provider.useFactory, provider.deps); } else { // { provide: 'API_URL', useValue: 'http://my.api.com/v1' } factoryFn = () => provider.useValue; // const _EMPTY_LIST: any[] = []; resolvedDeps = _EMPTY_LIST; } return new ResolvedReflectiveFactory(factoryFn, resolvedDeps); }步骤三 —— 合并已解析的Provider
const resolvedProviderMap = mergeResolvedReflectiveProviders(resolved, new Map()); export function mergeResolvedReflectiveProviders( providers: ResolvedReflectiveProvider[], normalizedProvidersMap: Map<number, ResolvedReflectiveProvider>): Map<number, ResolvedReflectiveProvider> { for (let i = 0; i < providers.length; i++) { const provider = providers[i]; // 从normalizedProvidersMap对象中获取key.id对应的ResolvedReflectiveProvider对象 const existing = normalizedProvidersMap.get(provider.key.id); if (existing) { // 如果当前的provider不是multi provider,则抛出异常 if (provider.multiProvider !== existing.multiProvider) { throw mixingMultiProvidersWithRegularProvidersError(existing, provider); } // 如果当前的provider是multi provider,则把当前provider的resolvedFactories // 列表中的每一项添加到已存在的provider对象的resolvedFactories列表中。 if (provider.multiProvider) { for (let j = 0; j < provider.resolvedFactories.length; j++) { existing.resolvedFactories.push(provider.resolvedFactories[j]); } } else { // 如果当前的provider不是multi provider,则覆盖已存在的provider normalizedProvidersMap.set(provider.key.id, provider); } } else { let resolvedProvider: ResolvedReflectiveProvider; // 如果当前的provider是multi provider,则创建一个新的ResolvedReflectiveProvider对象 if (provider.multiProvider) { resolvedProvider = new ResolvedReflectiveProvider_( provider.key, provider.resolvedFactories.slice(), provider.multiProvider); } else { resolvedProvider = provider; } // 在normalizedProvidersMap中保存已解析的ResolvedReflectiveProvider对象 normalizedProvidersMap.set(provider.key.id, resolvedProvider); } } return normalizedProvidersMap; }步骤四 —— 生成ResolvedReflectiveProvider[]
// resolvedProviderMap的values,创建ResolvedReflectiveProvider[] Array.from(resolvedProviderMap.values()); /** * 基于一个类似数组或可迭代对象创建一个新的数组实例 * * arrayLike:转换成真实数组的类数组对象或可遍历对象。 * mapFn(可选):如果指定了该参数,则最后生成的数组会经过该函数的加工处理后再返回。 * thisArg(可选):执行mapFn函数时this的值。 */ Array.from(arrayLike[, mapFn[, thisArg]])fromResolvedProviders()
该方法用于基于已解析的 providers 创建注入器。
static fromResolvedProviders(providers: ResolvedReflectiveProvider[], parent"htmlcode">@Injectable() class Engine {} @Injectable() class Car { constructor(public engine:Engine) {} } var providers = ReflectiveInjector.resolve([Car, Engine]); var injector = ReflectiveInjector.fromResolvedProviders(providers); expect(injector.get(Car) instanceof Car).toBe(true);了解完
fromResolvedProviders()
方法的使用方式,接下来我们来重点分析一下ReflectiveInjector_
类。ReflectiveInjector_ 类
ReflectiveInjector_ 类的属性
// 构造次数 _constructionCounter: number = 0; // ResolvedReflectiveProvider列表 public _providers: ResolvedReflectiveProvider[]; // 父级注入器 public _parent: Injector|null; // ReflectiveKey id列表 keyIds: number[]; // 依赖对象列表 objs: any[];ReflectiveInjector_ 构造函数
export class ReflectiveInjector_ implements ReflectiveInjector { constructor(_providers: ResolvedReflectiveProvider[], _parent"htmlcode">// 基于Provider列表并创建子注入器 resolveAndCreateChild(providers: Provider[]): ReflectiveInjector { const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers); return this.createChildFromResolved(ResolvedReflectiveProviders); } // 基于已解析的ResolvedReflectiveProvider列表,创建子注入器 createChildFromResolved(providers: ResolvedReflectiveProvider[]): ReflectiveInjector { const inj = new ReflectiveInjector_(providers); inj._parent = this; return inj; }用于获取对象
// 获取当前注入器的父级注入器 get parent(): Injector|null { return this._parent; } // 获取token对应的依赖对象 get(token: any, notFoundValue: any = THROW_IF_NOT_FOUND): any { return this._getByKey(ReflectiveKey.get(token), null, notFoundValue); } // 根据ReflectiveKey及visibility可见性,获取对应的依赖对象 private _getByKey(key: ReflectiveKey, visibility: Self|SkipSelf|null, notFoundValue: any): any { // const INJECTOR_KEY = ReflectiveKey.get(Injector); if (key === INJECTOR_KEY) { return this; } // 判断该依赖对象是否使用@Self装饰器定义,表示从本级注入器获取依赖对象 if (visibility instanceof Self) { return this._getByKeySelf(key, notFoundValue); } else { // 使用默认的方式获取依赖对象 return this._getByKeyDefault(key, notFoundValue, visibility); } } // 从本级注入器获取依赖对象 _getByKeySelf(key: ReflectiveKey, notFoundValue: any): any { const obj = this._getObjByKeyId(key.id); return (obj !== UNDEFINED) "htmlcode">// 创建依赖对象 _new(provider: ResolvedReflectiveProvider): any { // 判断是否存在循环依赖 if (this._constructionCounter++ > this._getMaxNumberOfObjects()) { throw cyclicDependencyError(this, provider.key); } return this._instantiateProvider(provider); } // 获取最大的对象个数 private _getMaxNumberOfObjects(): number { return this.objs.length; } // 根据已解析的provider创建依赖对象。若是multi provider则,循环创建multi provider对象。 private _instantiateProvider(provider: ResolvedReflectiveProvider): any { if (provider.multiProvider) { const res = new Array(provider.resolvedFactories.length); for (let i = 0; i < provider.resolvedFactories.length; ++i) { res[i] = this._instantiate(provider, provider.resolvedFactories[i]); } return res; } else { return this._instantiate(provider, provider.resolvedFactories[0]); } } // 根据已解析的provider和已解析的工厂创建依赖对象 private _instantiate( provider: ResolvedReflectiveProvider, ResolvedReflectiveFactory: ResolvedReflectiveFactory): any { // 获取对象工厂函数 const factory = ResolvedReflectiveFactory.factory; // 获取工厂函数所依赖的对象列表 let deps: any[]; try { deps = ResolvedReflectiveFactory.dependencies .map(dep => this._getByReflectiveDependency(dep)); } catch (e) { if (e.addKey) { e.addKey(this, provider.key); } throw e; } // 调用对象工厂函数创建依赖对象 let obj: any; try { obj = factory(...deps); } catch (e) { throw instantiationError(this, e, e.stack, provider.key); } return obj; }用于获取工厂函数依赖对象
// 若通过@Optional装饰器定义该依赖对象,表示该依赖对象是可选的,当获取不到时返回null。 private _getByReflectiveDependency(dep: ReflectiveDependency): any { return this._getByKey(dep.key, dep.visibility, dep.optional ? null : THROW_IF_NOT_FOUND); }以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
极乐门资源网 Design By www.ioogu.com极乐门资源网 免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com极乐门资源网 Design By www.ioogu.com暂无详解Angular 4.x Injector的评论...
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]