NestJS依赖注入工作原理
一、DI 容器概念
1.1 什么是 DI 容器
概念说明
DI 容器是 NestJS 管理所有类实例的公共区域,负责依赖注入的初始化和管理。
形象理解
code
DI 容器理解:
不是 Docker 容器
│
└── Docker:虚拟化技术,隔离运行环境
是一个公共的大对象
│
├── 管理所有类的实例
├── 管理类之间的依赖关系
└── 提供统一的访问入口
类比理解:
│
├── DI 容器 = 仓库
│ ├── 存放所有商品(类实例)
│ ├── 记录商品关系(依赖关系)
│ └── 按需提供商品(依赖注入)
│
└── 类实例 = 商品
├── 需要登记才能入库
└── 需要登记才能取用1.2 DI 容器的作用
code
DI 容器核心作用:
│
├── 注册管理
│ ├── 扫描所有 @Injectable 标记的类
│ ├── 注册到 DI 容器中
│ └── 创建实例映射表
│
├── 依赖解析
│ ├── 分析类构造器中的依赖
│ ├── 构建依赖关系图
│ └── 按拓扑排序创建实例
│
├── 实例创建
│ ├── 自动创建类实例
│ ├── 自动注入依赖
│ └── 管理实例生命周期
│
└── 依赖注入
├── 按需提供实例
├── 单例模式管理
└── 解决循环依赖二、DI 初始化流程
2.1 完整初始化流程
NestJS 启动时的 DI 流程
code
NestJS DI 初始化流程(从上至下):
1⃣ 扫描 @Injectable 标记的类
│
├── 扫描所有 Module 的 providers
├── 扫描所有 @Injectable 装饰器
└── 收集所有需要注册的类
▼
2⃣ 读取构造器依赖关系
│
├── 分析每个类的 constructor
├── 识别构造器参数中的依赖
└── 构建依赖关系图
▼
3⃣ 自动创建类实例
│
├── 按依赖关系拓扑排序
├── 递归创建依赖实例
└── 注入到构造器中
▼
4⃣ 管理实例生命周期
│
├── 单例模式存储实例
├── 提供实例访问接口
└── 处理实例销毁
▼
5⃣ 应用启动完成
│
└── 所有依赖注入完成,应用就绪2.2 详细步骤解析
第一步:扫描 @Injectable 标记的类
typescript
// ========== NestJS 扫描过程 ==========
// src/users/users.service.ts
import { Injectable } from '@nestjs/common';
@Injectable() // 标记为可注入
export class UsersService {
// ...
}
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
@Module({
providers: [UsersService], // 注册到 providers
controllers: [UsersController],
})
export class UsersModule {}
// ========== DI 容器扫描 ==========
// NestJS 启动时会扫描:
// 1. 所有 Module 的 providers 数组
// 2. 所有带 @Injectable 装饰器的类
// 3. 记录类名、类定义、作用域等信息第二步:读取构造器依赖关系
typescript
// ========== 构造器依赖分析 ==========
// src/users/users.service.ts
@Injectable()
export class UsersService {
constructor(
private readonly logger: LoggerService, // 依赖 LoggerService
private readonly repository: UsersRepository, // 依赖 UsersRepository
) {}
}
// src/orders/orders.service.ts
@Injectable()
export class OrdersService {
constructor(
private readonly usersService: UsersService, // 依赖 UsersService
) {}
}
// ========== DI 容器分析 ==========
// NestJS 会分析构造器,构建依赖关系图:
//
// UsersService
// ├── LoggerService
// └── UsersRepository
//
// OrdersService
// └── UsersService
// ├── LoggerService
// └── UsersRepository
// 拓扑排序后创建顺序:
// 1. LoggerService
// 2. UsersRepository
// 3. UsersService(依赖 1 和 2)
// 4. OrdersService(依赖 3)第三步:自动创建类实例
typescript
// ========== 自动实例化过程 ==========
// 传统方式:手动创建实例
const logger = new LoggerService();
const repository = new UsersRepository();
const usersService = new UsersService(logger, repository);
const ordersService = new OrdersService(usersService);
// NestJS 方式:自动创建实例
// DI 容器自动完成:
// 1. 创建 LoggerService 实例
// 2. 创建 UsersRepository 实例
// 3. 创建 UsersService 实例(注入 logger 和 repository)
// 4. 创建 OrdersService 实例(注入 usersService)
// 只需要声明依赖关系:
@Injectable()
export class OrdersService {
constructor(private readonly usersService: UsersService) {}
// DI 容器自动注入 usersService 实例
}三、Module 属性详解
3.1 四大核心属性
@Module 装饰器属性
typescript
import { Module } from '@nestjs/common';
@Module({
imports: [], // 导入其他模块
controllers: [], // 控制器
providers: [], // 服务提供者
exports: [], // 导出给其他模块使用
})
export class UsersModule {}属性作用详解
code
@Module 四大属性作用:
┌─────────────────────────────────────────────┐
│ providers │
│ ┌────────────────────────────────────────┐ │
│ │ 告诉 DI 系统:把下面的类初始化成实例 │ │
│ │ • 注册类到 DI 容器 │ │
│ │ • 自动创建实例 │ │
│ │ • 仅在当前模块内可用 │ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ exports │
│ ┌────────────────────────────────────────┐ │
│ │ 告诉 NestJS:下面的类需要在外部使用 │ │
│ │ • 导出类的实例 │ │
│ │ • 允许其他模块使用 │ │
│ │ • 必须先在 providers 中注册 │ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ imports │
│ ┌────────────────────────────────────────┐ │
│ │ 导入其他模块 │ │
│ │ • 获取其他模块导出的实例 │ │
│ │ • 使用其他模块的 providers │ │
│ │ • 建立模块间依赖关系 │ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ controllers │
│ ┌────────────────────────────────────────┐ │
│ │ 注册控制器 │ │
│ │ • 从 DI 容器获取实例 │ │
│ │ • 声明与 Service 的依赖关系 │ │
│ │ • 隶属于当前模块 │ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘3.2 providers 详解
作用:告诉 DI 系统初始化类实例
typescript
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersRepository } from './users.repository';
@Module({
providers: [
// 告诉 DI 系统:把下面的类放到 DI 容器中初始化
UsersService,
UsersRepository,
],
})
export class UsersModule {}
// ========== 相当于 ==========
// 手动创建实例(伪代码)
const diContainer = {
usersService: new UsersService(),
usersRepository: new UsersRepository(),
};
// 控制反转:由 DI 系统自动创建实例,而不是手动 new3.3 exports 详解
作用:告诉 NestJS 这个类需要在其他地方使用
typescript
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
@Module({
providers: [UsersService], // 1⃣ 注册到 DI 容器
exports: [UsersService], // 2⃣ 导出给其他模块使用
})
export class UsersModule {}
// src/orders/orders.module.ts
import { Module } from '@nestjs/common';
import { UsersModule } from '../users/users.module';
import { OrdersService } from './orders.service';
@Module({
imports: [UsersModule], // 导入 UsersModule 后可以使用 UsersService
providers: [OrdersService],
})
export class OrdersModule {}
// src/orders/orders.service.ts
import { Injectable } from '@nestjs/common';
import { UsersService } from '../users/users.service';
@Injectable()
export class OrdersService {
constructor(private readonly usersService: UsersService) {}
// 可以注入 UsersService(因为 UsersModule 导出了它)
}exports 使用规则
code
exports 使用规则:
正确使用:
│
├── 1. 先在 providers 中注册
│ providers: [UsersService]
│
├── 2. 再在 exports 中导出
│ exports: [UsersService]
│
└── 3. 其他模块 import 后可用
imports: [UsersModule]
错误使用:
│
├── 只写 exports,不写 providers
│ exports: [UsersService] // 未注册
│
└── 结果:无法创建实例,注入失败3.4 imports 详解
作用:导入其他模块,使用其导出的实例
typescript
// src/orders/orders.module.ts
import { Module } from '@nestjs/common';
import { UsersModule } from '../users/users.module';
import { AuthModule } from '../auth/auth.module';
@Module({
imports: [
UsersModule, // 导入 UsersModule,可使用其 exports 的 Service
AuthModule, // 导入 AuthModule,可使用其 exports 的 Service
],
providers: [OrdersService],
})
export class OrdersModule {}
// ========== 查找路径 ==========
// OrdersService 需要 UsersService
// 1. 查找 orders.module 的 providers → 没有
// 2. 查找 orders.module 的 imports → 有 UsersModule
// 3. 查找 users.module 的 providers → 有 UsersService
// 4. 查找 users.module 的 exports → 有 UsersService
// 5. 找到了,注入成功3.5 controllers 详解
作用:注册控制器,从 DI 容器获取实例
typescript
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
@Module({
controllers: [UsersController], // 注册控制器
providers: [UsersService],
})
export class UsersModule {}
// src/users/users.controller.ts
import { Controller } from '@nestjs/common';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
// 从 DI 容器获取 UsersService 实例
// 告诉 DI 系统:UsersController 依赖 UsersService
}控制器依赖查找规则
code
控制器依赖查找规则:
UsersController 依赖 UsersService
│
├── UsersController 隶属于 UsersModule
│
└── UsersModule 必须包含 UsersService
│
├── 方式一:providers 中注册
│ providers: [UsersService]
│
└── 方式二:imports 中导入包含 UsersService 的模块
imports: [OtherModule] // OtherModule 导出了 UsersService
如果都没有:DI 系统报错
"Nest can't resolve dependencies of the UsersController (?).
Please make sure that the argument UsersService at index [0]
is available in the UsersModule context."四、依赖查找机制
4.1 依赖查找路径
完整查找流程
code
依赖查找路径(以 Controller 注入 Service 为例):
┌─────────────────────────────────────────────┐
│ Controller 需要注入 UsersService │
└────────────────┬────────────────────────────┘
│
▼
┌────────────────┐
│ 查找当前模块 │
│ 的 providers │
└────────┬───────┘
│
┌───────┴───────┐
│ │
找到了 没找到
│ │
▼ ▼
注入实例 查找 imports
│
▼
┌──────────────┐
│ 遍历 imports │
│ 中的 Module │
└──────┬───────┘
│
▼
┌──────────────┐
│ 查找导入模块 │
│ 的 exports │
└──────┬───────┘
│
┌──────┴──────┐
│ │
找到了 没找到
│ │
▼ ▼
注入实例 DI 报错 4.2 完整示例演示
场景:OrdersController 需要 UsersService
typescript
// ========== 场景一:providers 中直接注册 ==========
// src/orders/orders.module.ts
import { Module } from '@nestjs/common';
import { OrdersController } from './orders.controller';
import { OrdersService } from './orders.service';
import { UsersService } from '../users/users.service';
@Module({
controllers: [OrdersController],
providers: [
OrdersService,
UsersService, // 直接在 providers 中注册
],
})
export class OrdersModule {}
// src/orders/orders.controller.ts
@Controller('orders')
export class OrdersController {
constructor(
private readonly ordersService: OrdersService,
private readonly usersService: UsersService, // 注入成功
) {}
}
// ========== 查找路径 ==========
// 1. OrdersController 需要 UsersService
// 2. 查找 orders.module 的 providers → 有 UsersService
// 3. 注入成功
// ========== 场景二:通过 imports 导入 ==========
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
@Module({
providers: [UsersService], // 注册到 DI 容器
exports: [UsersService], // 导出给其他模块使用
})
export class UsersModule {}
// src/orders/orders.module.ts
import { Module } from '@nestjs/common';
import { UsersModule } from '../users/users.module';
import { OrdersController } from './orders.controller';
import { OrdersService } from './orders.service';
@Module({
imports: [UsersModule], // 导入 UsersModule
controllers: [OrdersController],
providers: [OrdersService],
})
export class OrdersModule {}
// src/orders/orders.controller.ts
@Controller('orders')
export class OrdersController {
constructor(
private readonly ordersService: OrdersService,
private readonly usersService: UsersService, // 注入成功
) {}
}
// ========== 查找路径 ==========
// 1. OrdersController 需要 UsersService
// 2. 查找 orders.module 的 providers → 没有 UsersService
// 3. 查找 orders.module 的 imports → 有 UsersModule
// 4. 查找 users.module 的 providers → 有 UsersService
// 5. 查找 users.module 的 exports → 有 UsersService
// 6. 注入成功
// ========== 场景三:未找到依赖(错误示例)==========
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
@Module({
providers: [UsersService],
// 忘记导出 UsersService
})
export class UsersModule {}
// src/orders/orders.module.ts
import { Module } from '@nestjs/common';
import { UsersModule } from '../users/users.module';
import { OrdersController } from './orders.controller';
@Module({
imports: [UsersModule],
controllers: [OrdersController],
// providers 中也没有 UsersService
})
export class OrdersModule {}
// src/orders/orders.controller.ts
@Controller('orders')
export class OrdersController {
constructor(private readonly usersService: UsersService) {}
// 注入失败
}
// ========== 错误信息 ==========
// Nest can't resolve dependencies of the OrdersController (?).
// Please make sure that the argument UsersService at index [0]
// is available in the OrdersModule context.
// ========== 解决方案 ==========
// 方案一:在 users.module 中导出 UsersService
// exports: [UsersService]
// 方案二:在 orders.module 的 providers 中注册 UsersService
// providers: [UsersService]4.3 查找路径总结
code
依赖查找路径总结:
Controller 需要 Service
│
├── 路径一:providers 直接注册
│ └── module.providers 包含 Service
│
└── 路径二:imports 导入模块
├── module.imports 包含 Module
├── 该 Module.providers 包含 Service
└── 该 Module.exports 包含 Service
错误情况:
├── providers 和 imports 都没有 → DI 报错
└── imports 有但 exports 没有 → DI 报错
关键点:
├── providers:注册到 DI 容器
├── exports:允许外部使用
├── imports:导入其他模块
└── 查找顺序:providers → imports五、DI 系统工作流程图
5.1 完整工作流程
code
NestJS DI 系统完整工作流程:
┌─────────────────────────────────────────────────────┐
│ 应用启动 │
│ (main.ts) │
└─────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 扫描 AppModule │
│ (根模块及其依赖树) │
└─────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 扫描所有 Module 的 providers │
│ 收集所有 @Injectable 标记的类 │
└─────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 分析构造器依赖关系 │
│ constructor(private service: Service) │
└─────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 构建依赖关系图 │
│ 拓扑排序确定创建顺序 │
└─────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 按顺序创建实例 │
│ 1. 创建无依赖的实例 │
│ 2. 创建有依赖的实例(注入依赖) │
│ 3. 存储到 DI 容器 │
└─────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 初始化 Controller │
│ 注入依赖的 Service 实例 │
└─────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 应用就绪 │
│ 所有依赖注入完成 │
└─────────────────────────────────────────────────────┘5.2 模块依赖关系示例
code
模块依赖关系示例:
AppModule(根模块)
│
├── imports: [UsersModule, OrdersModule, AuthModule]
│
├── controllers: [AppController]
│ └── 依赖: AppService
│
└── providers: [AppService]
└── AppService 实例存储在 DI 容器
UsersModule
│
├── imports: [AuthModule]
│
├── controllers: [UsersController]
│ └── 依赖: UsersService
│
├── providers: [UsersService, UsersRepository]
│ ├── UsersService 依赖: UsersRepository, LoggerService
│ └── UsersRepository
│
└── exports: [UsersService]
└── 导出给其他模块使用
OrdersModule
│
├── imports: [UsersModule]
│ └── 可使用 UsersModule 导出的 UsersService
│
├── controllers: [OrdersController]
│ └── 依赖: OrdersService, UsersService
│
├── providers: [OrdersService]
│ └── OrdersService 依赖: UsersService(从 UsersModule 注入)
│
└── exports: [OrdersService]
AuthModule
│
├── imports: []
│
├── controllers: [AuthController]
│ └── 依赖: AuthService
│
├── providers: [AuthService, JwtService]
│ └── AuthService 依赖: JwtService
│
└── exports: [AuthService, JwtService]
DI 容器实例映射表:
{
AppService: AppService 实例,
UsersService: UsersService 实例,
UsersRepository: UsersRepository 实例,
OrdersService: OrdersService 实例,
AuthService: AuthService 实例,
JwtService: JwtService 实例,
}六、常见错误与解决方案
6.1 依赖未注册错误
错误信息
code
Nest can't resolve dependencies of the UsersController (?).
Please make sure that the argument UsersService at index [0]
is available in the UsersModule context.错误原因
typescript
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
// import { UsersService } from './users.service';
@Module({
controllers: [UsersController],
providers: [
// 忘记注册 UsersService
],
})
export class UsersModule {}
// src/users/users.controller.ts
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
// 无法注入 UsersService
}解决方案
typescript
// 方案一:在 providers 中注册
@Module({
controllers: [UsersController],
providers: [UsersService], // 注册 UsersService
})
export class UsersModule {}
// 方案二:通过 imports 导入
// src/shared/shared.module.ts
@Module({
providers: [UsersService],
exports: [UsersService],
})
export class SharedModule {}
// src/users/users.module.ts
@Module({
imports: [SharedModule], // 导入包含 UsersService 的模块
controllers: [UsersController],
})
export class UsersModule {}6.2 未导出错误
错误信息
code
Nest can't resolve dependencies of the OrdersService (UsersService).
Please make sure that the argument UsersService at index [0]
is available in the OrdersModule context.错误原因
typescript
// src/users/users.module.ts
@Module({
providers: [UsersService],
// 忘记导出 UsersService
})
export class UsersModule {}
// src/orders/orders.module.ts
@Module({
imports: [UsersModule], // 导入了 UsersModule
providers: [OrdersService],
})
export class OrdersModule {}
// src/orders/orders.service.ts
@Injectable()
export class OrdersService {
constructor(private readonly usersService: UsersService) {}
// 无法注入 UsersService(未导出)
}解决方案
typescript
// 在 UsersModule 中导出 UsersService
@Module({
providers: [UsersService],
exports: [UsersService], // 导出 UsersService
})
export class UsersModule {}6.3 循环依赖错误
错误信息
code
Circular dependency detected错误原因
typescript
// src/users/users.service.ts
@Injectable()
export class UsersService {
constructor(private readonly ordersService: OrdersService) {}
// 依赖 OrdersService
}
// src/orders/orders.service.ts
@Injectable()
export class OrdersService {
constructor(private readonly usersService: UsersService) {}
// 依赖 UsersService
}
// UsersService ⇄ OrdersService 循环依赖解决方案
typescript
// 方案一:使用 forwardRef
// src/users/users.service.ts
import { forwardRef, Inject, Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {
constructor(
@Inject(forwardRef(() => OrdersService))
private readonly ordersService: OrdersService,
) {}
}
// src/orders/orders.service.ts
import { forwardRef, Inject, Injectable } from '@nestjs/common';
@Injectable()
export class OrdersService {
constructor(
@Inject(forwardRef(() => UsersService))
private readonly usersService: UsersService,
) {}
}
// 方案二:重构代码,提取共享逻辑
// src/common/shared.service.ts
@Injectable()
export class SharedService {
// 共享的业务逻辑
}
// src/users/users.service.ts
@Injectable()
export class UsersService {
constructor(private readonly sharedService: SharedService) {}
}
// src/orders/orders.service.ts
@Injectable()
export class OrdersService {
constructor(private readonly sharedService: SharedService) {}
}6.4 常见错误速查表
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
Nest can't resolve dependencies | 依赖未注册 | 在 providers 中注册或 imports 导入 |
is not available in the XXXModule context | 未在模块中注册 | 在对应 Module 的 providers 中注册 |
Circular dependency detected | 循环依赖 | 使用 forwardRef 或重构代码 |
Cannot find module 'XXX' | 模块路径错误 | 检查 import 路径 |
Provider is not part of this module | Provider 未注册 | 在 Module 的 providers 中注册 |
七、最佳实践
7.1 模块设计原则
code
模块设计最佳实践:
1⃣ 单一职责
│
├── 每个模块只负责一个业务领域
├── 不要创建"上帝模块"
└── 合理拆分大型模块
2⃣ 清晰的依赖关系
│
├── 使用 imports 明确依赖
├── 使用 exports 明确对外接口
└── 避免循环依赖
3⃣ 合理使用 exports
│
├── 只导出需要共享的 Service
├── 内部使用的 Service 不导出
└── 控制模块边界
4⃣ Provider 注册策略
│
├── 当前模块使用:providers 注册
├── 共享给其他模块:providers + exports
└── 全局使用:@Global() 模块7.2 代码组织建议
typescript
// 推荐:清晰的模块组织
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { UsersRepository } from './users.repository';
@Module({
// 导入其他模块
imports: [],
// 控制器
controllers: [UsersController],
// 服务提供者
providers: [
UsersService,
UsersRepository,
],
// 导出给其他模块使用
exports: [UsersService],
})
export class UsersModule {}
// 推荐:使用 Shared Module
// src/shared/shared.module.ts
import { Module, Global } from '@nestjs/common';
import { LoggerService } from './logger.service';
import { ConfigService } from './config.service';
@Global() // 全局模块
@Module({
providers: [LoggerService, ConfigService],
exports: [LoggerService, ConfigService],
})
export class SharedModule {}
// 其他模块自动可用 LoggerService 和 ConfigService
// 无需在 imports 中导入八、学习要点总结
核心要点
- DI 容器本质:管理所有类实例的公共区域,不是 Docker 容器
- 初始化流程:扫描 @Injectable → 分析构造器 → 构建依赖图 → 创建实例
- providers 作用:告诉 DI 系统初始化类实例
- exports 作用:告诉 NestJS 这个类需要在其他地方使用
- imports 作用:导入其他模块,使用其导出的实例
- 查找路径:providers → imports → exports
记忆技巧
code
快速记忆:
DI 容器 = 仓库(存实例)
providers = 入库(注册)
exports = 开门(允许取用)
imports = 进货(导入其他模块)
controllers = 取货(获取实例)
查找顺序:
providers → imports → exports行动建议
code
学习路径:
│
├── 第一阶段:理解概念(1 天)
│ ├── 理解 DI 容器
│ ├── 理解初始化流程
│ └── 理解四大属性作用
│
├── 第二阶段:实践练习(3 天)
│ ├── 创建多模块项目
│ ├── 实现模块间依赖
│ └── 解决依赖注入错误
│
└── 第三阶段:深入应用(持续)
├── 理解 DI 系统源码
├── 解决复杂依赖关系
└── 优化模块架构九、延伸学习资源
官方资源
练习建议
- 练习 1:创建一个多模块项目,实现模块间依赖
- 练习 2:模拟依赖注入错误,尝试解决
- 练习 3:使用 forwardRef 解决循环依赖
- 练习 4:实现一个 Shared Module
- 练习 5:绘制项目的依赖关系图
延伸思考
code
思考题:
│
├── DI 容器是如何实现单例模式的?
├── 为什么 providers 不能导入模块?
├── forwardRef 的原理是什么?
├── 如何设计合理的模块架构?
└── DI 系统对性能有什么影响?附录:DI 系统速查表
| 概念 | 作用 | 关键词 |
|---|---|---|
| DI 容器 | 管理实例 | 公共区域、大对象 |
| @Injectable | 标记可注入 | 注册到 DI 容器 |
| providers | 注册实例 | 告诉 DI 初始化 |
| exports | 导出实例 | 允许外部使用 |
| imports | 导入模块 | 使用其他模块实例 |
| 查找路径 | providers → imports | 依赖查找顺序 |
笔记整理完成时间:2026-03-07
下一章节预告:NestJS 数据库实战