依赖注入(DI) 是一个核心的 NestJS 模式,框架 自动创建并提供 类需要的依赖项,而不是由类本身构造它们。你在 constructor 中声明需要什么,NestJS 就会提供它——导致代码松耦合、易测试。
它的工作原理:在 constructor 中声明
ts
()
{
() {}
}
Nest 读取 constructor 的参数类型,查找对应注册的 providers,创建它们(如果尚未创建),并将其传入——自动解析整个依赖图。
1. A class is marked @Injectable() → it's a provider
2. The provider is registered in a module's `providers` array
3. Another class declares it as a constructor parameter
4. NestJS's IoC container resolves and INJECTS the instance automatically
@Module({
providers: [UsersService, DatabaseService, LoggerService], // register all providers
controllers: [UsersController],
})
export class UsersModule {}
// Nest's container now knows how to construct each and inject them where needed
✓ Loose coupling — classes depend on ABSTRACTIONS, not on constructing concrete deps
✓ Testability — inject MOCK dependencies in tests easily (no real DB needed)
✓ Reusability — one shared instance (singleton) used across the app
✓ Maintainability — change an implementation in one place (the module registration)
// in a test, provide a fake DatabaseService — no real database required
const module = await Test.createTestingModule({
providers: [
UsersService,
{ provide: DatabaseService, useValue: mockDatabase }, // inject a mock
],
}).compile();
由于类不构造其依赖项,你可以在测试时替换成 mocks——DI 使 NestJS 应用具有高度的可测试性。
// use injection tokens for config/values, not just classes
constructor(@Inject("CONFIG") private config: AppConfig) {}
依赖注入是支撑 NestJS 整个架构的基础模式——它是 controllers 获取 services、services 获取 repositories 和其他 services,以及整个应用如何连接在一起的方式。
理解它至关重要,因为几乎每个 NestJS 类都参与 DI:你在 constructor 中声明依赖项,框架的 IoC 容器自动解析并提供它们,消除了手动实例化和紧耦合。
这些好处是显著的,也是 NestJS 受重视的核心原因:松耦合(依赖于抽象)、可测试性(注入 mocks 而不是真实依赖——使彻底的单元测试变得简单)、可重用性(共享单例)和可维护性。
DI 借鉴自 Angular 和 Spring 等框架,掌握它——如何声明、注册、注入和模拟依赖项——对于构建结构良好、易于测试的 NestJS 应用是必要的,也是框架中最重要的概念之一,需要深入理解。