依赖注入
2019-12-09 本文已影响0人
zdxhxh
angular重要概念
一、依赖注入
依赖注入 : 所谓依赖注入,即将函数需要使用到自身外作用域的变量(依赖),将它以实参的形式显示注入到函数中——<<你不知道的JS中>>
依赖注入框架 : 使用依赖注入这种设计模式的框架
这个问题的出现背景是,在oop的设计模式中,类的构造函数需要依赖其他的类,这时候有两个缺点 :
- constructor就变得十分臃肿,原因是依赖的实例构建
- 你需要区分依赖类使用的设计模式(工厂 ? 构造函数 )
class Test {
constructor(a : A,b : B,c : C) {
this.a = a
this.b = b
this.c = c
}
}
new Test(new A(xxxx,xxx),B.getInstance(xxxx),new C(xxxx))
这时候,你需要将依赖提出来,然后在新建实例时注入实例.
main(){
const a = new A(xxxx,xxx)
const b = new B(xxxx)
const c = new C(xxxx)
const test = new Test(a,b,c)
}
这样的做法有以下不好之处 :
- a,b,c三个对象的创建每次都要手动创建,如果a、b、c三个对象是重复的对象,如都是
new Address('广东','清远','清城区','鹤堂街')
这样的对象,重复创建则会浪费内存 - 代码量大,能不能在构造函数上面动手脚
二、angular的依赖注入
angular的依赖注入框架 有以下三部分组成
- injector(注入器)
- provider(构建) 通知令牌构造对象的模式
- object(依赖)
在angular中提供这样一个对象,可以创建类的连接池
import { ReflectiveInjector } from '@angular/core';
在angular官方文档中,写道
这是一个已废弃的对象,该对象是一个反射依赖注入容器,用于实例化对象和解析依赖关系
它有这个方法 :
resolveAndCreate : 接受一个数组参数,解析该数组并返回相应的注入器
看以下代码 :
import { ReflectiveInjector,Inject } from '@angular/core';
class Id {
static getInstance(type: string): Id{
return new Id()
}
}
class Address {
province : string
city : string
street : string
district : string
constructor(province,city,district,street) {
this.province = province
this.city = city
this.district = district
this.street = street
}
}
class Person {
id : Id
address :Address
// @Inject 修饰形参 表示需要哪些依赖
constructor(@Inject(Id) id,@Inject(Address) address) {
this.id = id
this.address = address
}
}
// 创建一个单例 里面有相应的类与类对象的创建方式
const injector = ReflectiveInjector.resolveAndCreate([
{ provide : Person,useClass : Person},
{ provide : Address,useFactory : ()=>{
return new Address('广东','清远','清城区','鹤堂街')
}},
{ provide : Id,useFactory : ()=>{
return Id.getInstance('idCard')
}},
])
const person1 = injector.get(Person)
const person2 = injector.get(Person)
console.log(person1.address === person2.address,'logs true ')
但在angular中,并没有那么复杂,直接在构造函数中声明就可以了
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
// angular@Component注解还提供了这样一个字段
providers : [
{ provide : 'BASE_CONFIG', useValue : 'http://wwww.xxx.cn'}
]
})
export class AppComponent {
constructor(private appService: AppService,@Inject('BASE_CONFIG') config)) {
}
}
还有一点是,injector对象是有父子关系的,你可以这样子创建一个children injector
const injector = ReflectiveInjector.resolveAndCreate([
{ provide : Person,useClass : Person},
{ provide : Address,useFactory : ()=>{
return new Address('广东','清远','清城区','鹤堂街')
}},
{ provide : Id,useFactory : ()=>{
return Id.getInstance('idCard')
}},
])
const childrenInject = injector.resolveAndCreateChild([Person])
子injector的一个重要特性是,如果在它身上找不到相关依赖,就会去父injector找