IoC
IoC(Inversion of Control) 控制反转,是 Java Spring 中非常重要的思想和核心。
在面向对象的软件开发过程中,随着应用规模越来越庞大,对象之间的依赖关系也越来越复杂,经常会出现对象之间的多重依赖关系。
import A from './A'
import B from './B'
export class App {
constructor() {
this.a = new A()
this.b = new B()
}
}
在上面的示例代码中,App 依赖A、B,并在构造器中进行实例化。这就形成了耦合,当存在大量依赖或需求频繁变动时,应用会变得越来越难以维护。
为了解决对象间耦合度过高的问题,IoC出现了。
IoC是控制翻转,那么到底是哪些控制被反转了呢?答案是 获取依赖对象的过程被翻转了。
import Container from 'Container'
import A from './A'
import B from './B'
const container = new Container()
container.bind(A)
container.bind(B)
export class App {
constructor() {
this.a = container.get('A')
this.b = container.get('B')
}
}
如上面的代码所示,获取依赖对象的过程,由内部实例化变为由 IoC 容器来实例化。
DI
DI (Dependency Injection) 依赖注入,即应用运行期间,由 IoC 容器动态地注入依赖。nestjs 的依赖注入,深受 Angular 的影响。nestjs 中的 IoC 容器,就是 nestjs 运行时系统。下面对这个流程做一下简单说明。
首先定义一个提供者,或者说服务:
import { Injectable } from '@nestjs/common'
@Injectable()
export class UserService {
findAll() {
return []
}
}
然后将提供者作为依赖,注入控制器类中使用:
import { Controller, Get } from '@nestjs/common'
import { UserService } from './user.service'
@Controller('user')
export class UserController {
// 声明所需依赖
constructor(private readonly userService: UserService) {}
@Get()
async findAll() {
return this.userService.findAll()
}
}
最后,在 IoC 容器中注册提供者:
import { Module } from '@nestjs/common';
import { UserController } from './user/user.controller';
import { UserService } from './user/user.service';
@Module({
controllers: [UserController],
providers: [UserService],
})
export class AppModule {}
通过上述步骤,IoC 容器就会为 UserController 自动注入实例。这里有三个关键步骤:
- 在 service 中用 @Injectable 声明一个可以由 IoC 容器管理的类。
- 在 controller 的构造函数中声明依赖。
- 在 app.module.ts 中,注册 UserService 类。
更多详细说明,请参考 自定义提供者。