Angular依赖注入
一、概述
依赖注入(Dependency Injection)简称DI,是面向对象编程中的一种设计原则,用来减少代码之间的耦合度。
class MailService{
constructor(APPIKEY){}
}
class EmailSender{
mailService:MailService
constructor(){
this.mailService=new MailService("ASDFEWDSF")
}
sendMail(mail){
this.mailService.sendMail(mail)
}
}
const emailSender=new EmailSender()
emailSender.sendMail(email)
EmailSender类运行时要使用MailService类,EmailSender类依赖MailService类,MailService类是EmailSender类的依赖项。
以上写法的耦合度太高,代码并不健壮。如果MailService类改变了参数的传递方式(之前在内部实例化写法固定),在EmailSender类中的写法也要跟着改变。
class EmailSender{
mailService MailService
constructor(mailService:MailService){
this.mailService=mailService;
}
}
const mailService=new MailService("asefsdfefs")
const emailSender=new EmailSender(mailService)
在实例化EmailService类时将它的依赖项通过constructor构造函数参数的形式注入到类的内部,这样写法就是依赖注入。
通过依赖注入降低代码之间的耦合度,增加了代码的可维护性,MailService类中的代码的更改再也不会影响EmailSender类。
二、DI框架
Angular有自己的DI框架,它将实现依赖注入的过程隐藏了,对于开发者来说只需使用很简单的代码就可以使用复杂的依赖注入功能
在Angular的DI框架中有四个核心概念:
1)Dependency:组件要依赖的实例对象,服务实例对象
2)Token:获取服务实例对象的标识
3)Injector:注入器,负责创建维护服务类的实例对象并向组件中注入服务实例对象。
4)Provider:配置注入器的对象,指定创建服务实例对象的服务类和获取实例对象的标识。
1.注入器Injections
注入器负责创建服务类实例对象,并将服务类实例对象注入到需要的组件中。
1)创建注入器
import {ReflectiveInjector} from "@angular/core"
//服务类
class MailService{}
//创建注入器并传入服务类
const injector=ReflectiveInjector.resolveAndCreate([MailService])
2)获取注入器中的服务类实例对象
const mailService=injector.get(MailService)
3)服务实例对象为单例模式,注入器在创建服务实例后会对其进行缓存
const mailService1=injector.get(MailService)
const mailService2=injector.get(MailService)
console.log(mailService1===mailService2) //true
4)不同的注入器返回不同的服务实例对象
const injector=ReflectiveInjector.resolveAndCreate([MailService])
const childInjector=injector.resolveAndCreateChild([MailService])
const mailService1=injector.get(MailService)
const mailService2=childInjector.get(MailService)
console.log(mailService1===mailService2) //false
5)服务实例的查找类似函数作用域链,当前级别可以找到就使用当前级别,当前级别找不到去父级中找到
const injector=ReflectiveInjector.resolveAndCreate([MailService])
const childInjector=injector.resolveAndCreateChild([])
const mailService1=injector.get(MailService)
const mailService2=childInjector.get(MailService)
console.log(mailService1===mailService2) //true
2.提供者Provider
1)配置注入器的对象,指定了创建实例对象的服务类和访问服务实例对象的标识。
const injector=ReflectiveInjector.resolveAndCreate([{
provide:MailService,useClass:MailService
}])
2)访问依赖对象的标识也可以是字符串类型
const injector=ReflectiveInjector.resolveAndCreate([
{provide:"mail",useClass:MailService}
])
const mailService=injector.get("mail");
3)useValue
const injector=ReflectiveInjector.resolveAndCreate([
{
provide:"mail",
//useValue:{name:"张三",age:1}
useValue:Object.freeze({ //冰结,防止外部修改
name:"张三",
age:20
})
}
])
const mailService=injector.get("mail")
mailService.name="李四";//不可修改
console.log(mailService);
将实例对象和外部的引用建立了松耦合关系,外部通过标识获取实例对象,只要标识保持不变,内部代码怎么变都不会影响到外部。
不足之处望指正