依赖注入:设计模式
依赖:程序里需要的某种类型的对象。
依赖注入框架:工程化的框架

注入者Injector:用它的API创建依赖的实例
Provider:怎样创建?(构造函数,工程函数)
Object:组件,模块需要的依赖
依赖性注入进阶=>父子层次依赖
一、依赖注入
class Id { static getInstance(type: string): Id { return new Id(); } } class Address { constructor(provice, city, district, street) {} } class Person { id: Id; address: Address; constructor() { this.id = Id.getInstance("idcard"); this.address = new Address("北京", "背景", "朝阳区", "xx街道"); } }
问题:Person需要清楚的知道Address和Id的实现细节。
ID和Address重构后,Person需要知道怎么重构。
项目规模扩大后,集成容易出问题。
class Id { static getInstance(type: string): Id { return new Id(); } } class Address { constructor(provice, city, district, street) {} } class Person { id: Id; address: Address; constructor(id: Id, address: Address) { this.id = id; this.address = address; } } main(){ //把构造依赖对象,推到上一级,推调用的地方 const id = Id.getInstance("idcard"); const address = new Address("北京", "背景", "朝阳区", "xx街道"); const person = new Person(id , address); }
Person已经不知道Id和Address的细节了。
这是最简单的依赖注入。
问题是在main里还是需要知道细节。
思路:一级一级往上推,一直推到入口函数,入口函数来处理所有对象的构造。构造出来后提供给所有依赖的子模块的子类。
问题:入口函数很难维护。所以需要一个依赖注入框架帮助完成。
二、Angular的依赖注入框架
ReflectiveInjector :
import { Component ,ReflectiveInjector } from "@angular/core";
resolveAndCreate接收一个provider数组,provider告诉injector应该怎样去构造这个对象。
constructor() { //接收一个provider数组 const injector = ReflectiveInjector.resolveAndCreate([ { provide: Person, useClass:Person }, { provide: Address, useFactory: ()=>{ if(environment.production){ return new Address("北京", "背景", "朝阳区", "xx街道xx号"); }else{ return new Address("西藏", "拉萨", "xx区", "xx街道xx号"); } } }, { provide: Id, useFactory:()=>{ return Id.getInstance('idcard'); } } ]); }
Injector:
injector相当于main函数,可以拿到所有依赖池子里的东西。
import { Component ,ReflectiveInjector, Inject} from "@angular/core";
import { OverlayContainer } from "@angular/cdk/overlay";
import { Identifiers } from "@angular/compiler";
import { stagger } from "@angular/animations";
import { environment } from 'src/environments/environment';
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"]
})
export class AppComponent {
constructor(private oc: OverlayContainer) {
//接收一个provider数组
const injector = ReflectiveInjector.resolveAndCreate([
{
provide: Person, useClass:Person
},
{
provide: Address, useFactory: ()=>{
if(environment.production){
return new Address("北京", "背景", "朝阳区", "xx街道xx号");
}else{
return new Address("西藏", "拉萨", "xx区", "xx街道xx号");
}
}
},
{
provide: Id, useFactory:()=>{
return Id.getInstance('idcard');
}
}
]);
const person = injector.get(Person);
console.log(JSON.stringify(person));
}
}
class Id {
static getInstance(type: string): Id {
return new Id();
}
}
class Address {
provice:string;
city:string;
district:string;
street:string;
constructor(provice, city, district, street) {
this.provice=provice;
this.city=city;
this.district=district;
this.street=street;
}
}
class Person {
id: Id;
address: Address;
constructor(@Inject(Id) id, @Inject(Address )address) {
this.id = id;
this.address = address;
}
}
可以看到控制台打印出person信息。

简写:
// { // provide: Person, useClass:Person // }, Person, //简写为Person
在Angular框架中,框架做了很多事,在provider数组中注册的东西会自动注册到池子中。
@NgModule({ imports: [HttpClientModule, SharedModule, AppRoutingModule, BrowserAnimationsModule], declarations: [components], exports: [components, AppRoutingModule, BrowserAnimationsModule], providers:[ {provide:'BASE_CONFIG',useValue:'http://localhost:3000'} ] })
constructor( @Inject('BASE_CONFIG') config) {
console.log(config); //控制台打印出http://localhost:3000
}
Angular默认都是单例,如果想要每次注入都是一个新的实例。有两种方法。
一,return的时候return一个方法而不是对象。
{ provide: Address, useFactory: ()=>{ return ()=>{ if(environment.production){ return new Address("北京", "背景", "朝阳区", "xx街道xx号"); }else{ return new Address("西藏", "拉萨", "xx区", "xx街道xx号"); } } } },
二、利用父子Injector。
constructor(private oc: OverlayContainer) { //接收一个provider数组 const injector = ReflectiveInjector.resolveAndCreate([ Person, { provide: Address, useFactory: ()=>{ if(environment.production){ return new Address("北京", "背景", "朝阳区", "xx街道xx号"); }else{ return new Address("西藏", "拉萨", "xx区", "xx街道xx号"); } } }, { provide: Id, useFactory:()=>{ return Id.getInstance('idcard'); } } ]); const childInjector = injector.resolveAndCreateChild([Person]); const person = injector.get(Person); console.log(JSON.stringify(person)); const personFromChild = childInjector.get(Person); console.log(person===personFromChild); //false }
子注入者当中没有找到依赖的时候会去父注入者中找。