DI依赖注入是一种编码模式,构造函数中的参数通过注入器获取不需要自己创建。@Inject是参数修饰符,表示该参数是通过注入的方式获取。依赖的内容可以是类,也可以是InjectionToken,通过@Inject注入的方法使用步骤如下:
1、如果在一个自己写的类注入另一个类
可以通过ReflectiveInjector.resolveAndCreate形式先创建,再通过get方法获取实例。
2、如果在组件中或者服务中使用
(1)先在component或者模块中先用provider注入一次,providers:[{provide:类名,useFactory等}]
(2)在construtor中通过@Inject注入实例
(3)如果注入的是interface或者字符串等则需要先生成InjectionToken.
具体示例如下:
通过一段代码表示依赖注入与@Inject的使用有A类,B类,B类依赖类A:
class A{
name:string;
age:Number;
constructor(n:string, a:number){
this.name = n;
this.age = a;
}
}
/**
* 通过依赖注入
*/
class B{
a;
constructor(
@Inject(A) a:A // 通过依赖注入
){
this.a = a;
}
}
const injector = ReflectiveInjector.resolveAndCreate([
{provide:A,useFactory:()=>{
return new A('a',34)
}},
Aa
]);
const b1 = new B(injector.get(A)); // 通过injector注入
const a1 = new A(new A('dd',23)); // 通过正常的方式注入
const a2 = injector.get(A); //通过injector获取
const a3 = injector.get(A);
console.log(a2==a3); // injector.get如果无会创建,如果有直接返回
在使用@Inject(Token) value:Token之前,需要通过provider注入值。一般我们在根模块中进行注入,而后在各个类中通过@Inject进行注入。
比如在模块中或者组件装饰器中使用[{provide:Aa,useFactory:()=>{return xxx}}]进行默认的初始化
InjectionToken(来自angular中文官网):
并非所有的依赖都是类。 有时候你会希望注入字符串、函数或对象。
应用通常会用大量的小型参数来定义配置对象,比如应用的标题或 Web API 端点的地址。 这些配置对象不一定总是类的实例。 它们还可能是对象字面量,如下例所示。
export const HERO_DI_CONFIG: AppConfig = {
apiEndpoint: 'api.heroes.com',
title: 'Dependency Injection'
};
TypeScript 接口不是有效的令牌
HERO_DI_CONFIG
常量满足 AppConfig
接口的要求。 不幸的是,你不能用 TypeScript 的接口作为令牌。 在 TypeScript 中,接口是一个设计期的概念,无法用作 DI 框架在运行期所需的令牌。
// FAIL! Can't use interface as provider token
[{ provide: AppConfig, useValue: HERO_DI_CONFIG })]
为非类依赖选择提供商令牌的解决方案是定义并使用 InjectionToken
对象。 下面的例子展示了如何定义那样一个令牌。
import { InjectionToken } from '@angular/core';
export const APP_CONFIG = new InjectionToken<AppConfig>('app.config');
//工厂
providers: [{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG }]
//注入
constructor(@Inject(APP_CONFIG) config: AppConfig) {
this.title = config.title;
}
InjectionToken的用法
class InjectionToken<T> {
constructor(_desc: string, options?: { providedIn?: Type<any> | "root"; factory: () => T; })
ngInjectableDef: never | undefined
protected _desc: string
toString(): string
}
/*使用案例*/
const BASE_URL = new InjectionToken<string>('BaseUrl');
const injector =
Injector.create({providers: [{provide: BASE_URL, useValue: 'http://localhost'}]});
const url = injector.get(BASE_URL);
// here `url` is inferred to be `string` because `BASE_URL` is `InjectionToken<string>`.
expect(url).toBe('http://localhost');