在介绍 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 抽象类子类有:
_NullInjector
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()
静态方法外,还含有以下静态方法:
resolve() - 解析 Provider 列表为 ResolvedReflectiveProvider 列表
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() 解析图示
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_ 类中的方法较多,我们只分析其中比较重要的方法,首先先根据方法的实现的功能进行分类:
用于创建ReflectiveInjector注入器
用于获取对象
用于创建对象
用于获取工厂函数依赖对象
用于创建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);
}
其实 Angular DI 最核心的内容是,如何创建依赖对象?在 Angular 中我们通过使用工厂函数,来创建依赖对象。工厂函数的输入参数是依赖对象列表,输出结果是对应的依赖对象。因此接下来我们将着重介绍如何创建工厂函数和如何创建依赖对象?但在开始介绍之前,我们还得先介绍一下 Angular Metadata 的相关内容。
Angular Metadata
在 Angular 中 Metadata 主要分为以下几种类型:
annotations
design:paramtypes
propMetadata
parameters
接下来我们来看一下具体示例:
友情提示:其中 design:paramtypes 和 parameters metadata 类型主要用于实现依赖注入
Angular 使用第三方库 core-js
提供的 Reflect API ,来实现对 Metadata 信息的存储与读取。
Metadata 信息的存储
我们以类装饰器为例,如 @Component()
、@NgModule()
:
// angular2/packages/core/src/util/decorators.ts
export function makeDecorator(
name: string,
props: {[name: string]: any},
parentClass?: any,
chainFn?: (fn: Function) => void): (...args: any[]) => (cls: any) => any {
//...
const TypeDecorator: TypeDecorator = <TypeDecorator>function TypeDecorator(cls:
Type<any>) {
const annotations = Reflect.getOwnMetadata('annotations', cls) || [];
annotations.push(annotationInstance);
// 保存annotations metadata信息
Reflect.defineMetadata('annotations', annotations, cls);
return cls;
};
}
Reflect.defineMetadata()
方法用来保存定义的 Metadata 信息,相应的 Metadata 信息是保存在 window['__core-js_shared__']
对象的 metadata 属性中。感兴趣的话,大家可以直接在控制台,输入 window['__core-js_shared__']
查看该对象的内部信息。介绍完 Metadata 信息的保存,我们来了解一下如何获取 Metadata 信息。
Metadata 信息的读取
Angular 中通过 ReflectorReader
抽象类,定义了读取 Metadata 信息相关的抽象方法:
export abstract class ReflectorReader {
abstract parameters(typeOrFunc: /*Type*/ any): any[][];
abstract annotations(typeOrFunc: /*Type*/ any): any[];
abstract propMetadata(typeOrFunc: /*Type*/ any): {[key: string]: any[]};
abstract importUri(typeOrFunc: /*Type*/ any): string|null;
abstract resourceUri(typeOrFunc: /*Type*/ any): string;
abstract resolveIdentifier(name: string, moduleUrl: string, members: string[],
runtime: any): any;
abstract resolveEnum(identifier: any, name: string): any;
}
上述抽象方法的具体实现类是 - Reflector
类:
// angular2/packages/core/src/reflection/reflector.ts
export class Reflector extends ReflectorReader {
constructor(public reflectionCapabilities: PlatformReflectionCapabilities) {
super();
}
//...
factory(type: Type<any>): Function { return this.reflectionCapabilities.factory(type); }
parameters(typeOrFunc: Type<any>): any[][] {
return this.reflectionCapabilities.parameters(typeOrFunc);
}
annotations(typeOrFunc: Type<any>): any[] {
return this.reflectionCapabilities.annotations(typeOrFunc);
}
propMetadata(typeOrFunc: Type<any>): {[key: string]: any[]} {
return this.reflectionCapabilities.propMetadata(typeOrFunc);
}
}
介绍完 Angular Metadata 的相关知识,我们来开始介绍如何创建依赖对象。
创建依赖对象
创建ResolvedReflectiveFactory
// 解析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);
}
useClass
// { provide: ApiService, useClass: ApiService }
const useClass = resolveForwardRef(provider.useClass);
factoryFn = reflector.factory(useClass);
resolvedDeps = _dependenciesFor(useClass);
设置工厂函数
// 获取通过forwardRef()方法定义的类
const useClass = resolveForwardRef(provider.useClass);
factoryFn = reflector.factory(useClass);
// reflector.factory() 方法
factory<T>(t: Type<T>): (args: any[]) => T {
return (...args: any[]) => new t(...args);
}
设置依赖对象列表
// 解析类中的依赖对象
function _dependenciesFor(typeOrFunc: any): ReflectiveDependency[] {
// 获取design:paramtypes和paramters保存的metadata信息
const params = reflector.parameters(typeOrFunc);
if (!params) return [];
if (params.some(p => p == null)) {
throw noAnnotationError(typeOrFunc, params);
}
return params.map(p => _extractToken(typeOrFunc, p, params));
}
// 创建ReflectiveDependency对象
function _extractToken(typeOrFunc: any, metadata: any[] | any,
params: any[][]):
ReflectiveDependency {
let token: any = null;
let optional = false;
if (!Array.isArray(metadata)) {
// Inject: InjectDecorator = makeParamDecorator('Inject', [['token',
// undefined]]);
if (metadata instanceof Inject) {
return _createDependency(metadata['token'], optional, null);
} else {
return _createDependency(metadata, optional, null);
}
}
let visibility: Self|SkipSelf|null = null;
// 遍历metadata数组,设置token、optional(可选的)、visibility(可见性)的值
for (let i = 0; i < metadata.length; ++i) {
const paramMetadata = metadata[i];
if (paramMetadata instanceof Type) {
token = paramMetadata;
} else if (paramMetadata instanceof Inject) {
token = paramMetadata['token'];
} else if (paramMetadata instanceof Optional) {
optional = true;
} else if (paramMetadata instanceof Self ||
paramMetadata instanceof SkipSelf) {
visibility = paramMetadata;
} else if (paramMetadata instanceof InjectionToken) {
token = paramMetadata;
}
}
// 获取通过forwardRef()方法定义的类
token = resolveForwardRef(token);
if (token != null) {
return _createDependency(token, optional, visibility);
} else {
throw noAnnotationError(typeOrFunc, params);
}
}
// 创建ReflectiveDependency对象
function _createDependency(
token: any, // 依赖对象关联的token
optional: boolean, // 是否是可选的
visibility: Self | SkipSelf | null): ReflectiveDependency {
return new ReflectiveDependency(
ReflectiveKey.get(token),
optional,
visibility);
}
useExisting
// { provide: 'ApiServiceAlias', useExisting: ApiService }
factoryFn = (aliasInstance: any) => aliasInstance;
resolvedDeps = [ReflectiveDependency
.fromKey(ReflectiveKey.get(provider.useExisting))];
设置工厂函数
factoryFn = (aliasInstance: any) => aliasInstance;
设置依赖对象列表
// { provide: 'ApiServiceAlias', useExisting: ApiService }
resolvedDeps = [ReflectiveDependency.fromKey(ReflectiveKey.get(provider.useExisting))];
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);
}
}
useFactory
// { provide: APP_INITIALIZER, useFactory: configFactory, deps: [AppConfig],
// multi: true }
factoryFn = provider.useFactory;
resolvedDeps = constructDependencies(provider.useFactory, provider.deps);
设置工厂函数
factoryFn = provider.useFactory;
设置依赖对象列表
resolvedDeps = constructDependencies(provider.useFactory, provider.deps);
// 构造ReflectiveDependency[]列表
export function constructDependencies(
typeOrFunc: any, dependencies?: any[]): ReflectiveDependency[] {
if (!dependencies) {
return _dependenciesFor(typeOrFunc);
} else {
const params: any[][] = dependencies.map(t => [t]);
return dependencies.map(t => _extractToken(typeOrFunc, t, params));
}
}
useValue
// { provide: 'API_URL', useValue: 'http://my.api.com/v1' }
factoryFn = () => provider.useValue;
resolvedDeps = _EMPTY_LIST; // const _EMPTY_LIST: any[] = [];
设置工厂函数
factoryFn = () => provider.useValue;
设置依赖对象列表
resolvedDeps = _EMPTY_LIST; // const _EMPTY_LIST: any[] = [];
现在 Angular Injector 的相关知识,已经介绍完了。由于涉及过多的源码,没介绍清楚的地方,请见谅。
我有话说
AngularJS 1.x 依赖注入存在的问题
内部缓存:AngularJS 1.x 应用程序中所有的依赖项都是单例,我们不能控制是否使用新的实例
命名空间冲突: 在系统中我们使用字符串来标识 service 的名称,假设我们在项目中已有一个 CarService,然而第三方库中也引入了同样的服务,这样的话就容易出现混淆
DI 耦合度太高: AngularJS 1.x 中 DI 功能已经被框架集成了,我们不能单独使用它的 DI 特性
未能和模块加载器结合: 在浏览器环境中,很多场景都是异步的过程,我们需要的依赖模块并不是一开始就加载好的,或许我们在创建的时候才会去加载依赖模块,再进行依赖创建,而 AngularJS 1.x 的 DI 系统没法做到这点。
详细的内容可以参考 - Angular 2 DI - IoC & DI - 1
Angular 注入器有什么特点?
Angular 中注入器是有层级结构的,即创建完注入器,我们可以基于它创建它的子注入器。
resolveAndCreate() - 根据设置的 provider 数组创建注入器
resolveAndCreateChild() - 调用已有注入器对象上的该方法,创建子注入器
当调用注入器 get()
方法,获取 token 对应的对象时,默认的查找方式是,优先从本级注入级获取,如果未找到,则往上一级查找,直到根级注入器。若未找到对应的依赖对象,默认会抛出异常。
使用示例
class ParentProvider {}
class ChildProvider {}
var parent = ReflectiveInjector.resolveAndCreate([ParentProvider]);
var child = parent.resolveAndCreateChild([ChildProvider]);
expect(child.get(ParentProvider) instanceof ParentProvider).toBe(true);
expect(child.get(ChildProvider) instanceof ChildProvider).toBe(true);
expect(child.get(ParentProvider)).toBe(parent.get(ParentProvider));
通过分析源码,我们也发现如果两个服务提供商 (Provider) 使用同一个 Token,却没有声明为 multi provider,那么后面的会把前面的覆盖掉。此外需要注意的是,multi provider 不能与普通的 provider 混用。
@Self()、@SkipSelf()、@Optional() 等装饰器有什么作用?
@Self() - 表示只在本级注入器查找依赖对象
@SkipSelf() - 表示不从本级注入器获取依赖对象
@Optional - 表示该依赖对象是可选的,如果找不到返回 null