HogoZhang
·493·2 分钟阅读·

nestjs的IOC控制反转 DI依赖注入

nestjs的核心设计模式。


在 NestJS 中,控制反转(IoC)依赖注入(DI) 是其核心设计模式,用于实现组件之间的解耦和可测试性。

控制反转(IoC)

将对象的创建和依赖关系的管理交给容器,而不是由组件自身去创建依赖。

传统方式中,类内部会 new 依赖对象,导致紧耦合。IoC 反转了控制流:“不要调用我们,我们调用你”。在 NestJS 里,IoC 容器(运行时系统)负责管理所有类的实例化与生命周期。

依赖注入(DI)

IoC 的一种具体实现形式:将依赖通过构造函数、属性或方法参数的方式“注入”到组件中。

NestJS 采用 构造函数注入 作为主要方式,并通过装饰器(@Injectable())来标识可被注入的类。

工作机制

  1. 标记可注入类:使用 @Injectable() 装饰器告诉 Nest 这个类可以被容器管理。

    @Injectable()
    export class UserService {
      findOne(id: number) { /* ... */ }
    }
  2. 声明依赖:在消费者(如控制器或其他服务)的构造函数中声明所需依赖的类型。

    @Controller('users')
    export class UserController {
      constructor(private userService: UserService) {}
      // 自动注入 UserService 实例
    }
  3. 容器实例化与注入:Nest 运行时会扫描所有 providers,创建依赖图,并按需实例化,然后将实例注入到需要的地方。

自定义 Provider 与作用域

  • 自定义 Provider:可以通过 useClassuseValueuseFactory 灵活提供注入内容。
    @Module({
      providers: [
        { provide: 'CONFIG', useValue: { apiKey: '123' } },
        { provide: UserService, useClass: CustomUserService },
        { provide: 'LOGGER', useFactory: (config) => new Logger(config), inject: ['CONFIG'] }
      ]
    })
  • 注入作用域:支持单例(默认)、请求级别、瞬态作用域,适应不同场景。

为什么需要 DI?

  • 解耦:高层模块不依赖低层模块的具体实现,依赖抽象。
  • 可测试性:单元测试时可以轻松替换为模拟(mock)对象。
  • 灵活管理生命周期:容器自动处理单例、请求级实例等。

总结

NestJS 的 IoC/DI 体系借鉴了 Angular 的思想,通过 @Injectable() 和构造函数注入,让开发者专注于业务逻辑,框架负责装配组件。这套机制是 NestJS 生态模块化、可扩展的基石。