欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解Angular 4.x Injector

程序员文章站 2022-06-03 12:31:21
在介绍 angular injector (注入器) 之前,我们先要了解 dependency injection,即依赖注入的概念。 依赖注入允许程序设计遵从依赖倒置原...

在介绍 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();

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;
 }
}

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() 静态方法外,还含有以下静态方法:

  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);
}

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

resolve()

该方法用于把 provider 数组解析为 resolvedreflectiveprovider 数组。

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() 解析图示

详解Angular 4.x Injector 

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;
}

resolvedreflectiveprovider 接口

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?: injector):
 reflectiveinjector {
  return new reflectiveinjector_(providers, parent);
}

fromresolvedproviders() 使用示例

@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?: injector) {
   this._providers = _providers;
   // 设置父级注入器
   this._parent = _parent || null;

   const len = _providers.length;

   this.keyids = new array(len);
   this.objs = new array(len);

   // 初始化keyids列表和objs对象列表
   for (let i = 0; i < len; i++) {
    this.keyids[i] = _providers[i].key.id;
    this.objs[i] = undefined;
   }
 }
}

const undefined = new object();

reflectiveinjector_ 类的方法

reflectiveinjector_ 类中的方法较多,我们只分析其中比较重要的方法,首先先根据方法的实现的功能进行分类:

  1. 用于创建reflectiveinjector注入器
  2. 用于获取对象
  3. 用于创建对象
  4. 用于获取工厂函数依赖对象

用于创建reflectiveinjector注入器

// 基于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) ? obj : this._throwornull(key, notfoundvalue);
}

// 使用默认的方式获取依赖对象
_getbykeydefault(key: reflectivekey, notfoundvalue: any, 
  visibility: self|skipself|null): any {
  let inj: injector|null;

  // 判断该依赖对象是否使用@skipself装饰器定义,表示不从本级注入器获取依赖对象
  if (visibility instanceof skipself) {
   inj = this._parent;
  } else {
   inj = this;
  }

  // 从本级注入器获取依赖对象,若本级获取不到,则从父级注入器中查找
  while (inj instanceof reflectiveinjector_) {
   const inj_ = <reflectiveinjector_>inj;
   const obj = inj_._getobjbykeyid(key.id);
   if (obj !== undefined) return obj;
   inj = inj_._parent;
  }
  if (inj !== null) {
   return inj.get(key.token, notfoundvalue);
  } else {
   return this._throwornull(key, notfoundvalue);
  }
}

// 获取keyid对应的对象,如依赖对象未创建,则调用_new()方法创建一个,然后保存到
// this.objs对象列表中
private _getobjbykeyid(keyid: number): any {
  for (let i = 0; i < this.keyids.length; i++) {
   if (this.keyids[i] === keyid) {
    // const undefined = new object();
    if (this.objs[i] === undefined) {
     this.objs[i] = this._new(this._providers[i]);
    }
    return this.objs[i];
   }
  }
  return undefined;
}

用于创建对象

// 创建依赖对象
_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);
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。