2021SC@SDUSC
依赖注入(控制反转):将控制权交给第三方(容器)
依赖注入(DI)和控制反转(IOC)基本是一个意思,因为说起来谁都离不开谁。
简单来说,a依赖b,但a不控制b的创建和销毁,仅使用b,那么b的控制权交给a之外处理,这叫控制反转(IOC),而a要依赖b,必然要使用b的instance,那么
-
通过a的接口,把b传入;
-
通过a的构造,把b传入;
-
通过设置a的属性,把b传入;
这个过程叫依赖注入(DI)。
本来我接受各种参数来构造一个对象,现在只接受一个参数——已经实例化的对象。
也就是说我对对象的『依赖』是注入进来的,而和它的构造方式解耦了。构造它这个『控制』操作也交给了第三方,也就是控制反转。
从资源的角度:
-
容器 - 是所有资源的管理者。程序中可被注入的资源都由容器来发起创建和维护其生命周期
-
资源提供者 - 资源创建的实际执行者。所有的资源提供者都需要在容器进行注册登记,然后由容器来进行统一调度
-
资源使用者 - 就是那些需要使用到容器中管理的那些资源的消费者了
资源提供者(provider)
-
第一种类型,是使用类作为提供者,称为ClassProvider。它也是我们日常开发中会最经常用到的一种资源提供者。一个普通的类,通过添加 @Inectable 装饰器,就可以成为一个资源提供者。
-
第二种类型,是使用常量值(可以是简单基础类型值,也可以是对象),称为ValueProvider。它非常适用于做配置性的工作,或者是Mock测试。
-
第三种类型,是使用工厂函数,称为FactoryProvider。它适用于需要更为动态的创建资源的场景。
-
第四种类型,其实是一种用于给其他已有的资源提供者创建其他别名的方式,称为ExistingProvider。
资源注入的方式
-
通过类的构造函数注入
-
通过类的属性注入
@Injectable()
export class CategoryService {
constructor(private readonly productService: ProductService) { }
}
//如果资源的注入令牌不是class类型的,则需要显式的使用 @Inject 装饰器来指定:
@Injectable()
export class CategoryService {
constructor(
@Inject('myProductService')
private readonly productService: ProductService) { }
}
//而通过属性的注入方式是另一种可选途径。
@Injectable()
export class CategoryService {
constructor(
@Optional()//非必须,可选的
@Inject('myProductService')
private readonly productService: ProductService) { }
}