{T}

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 系统自动创建实例,而不是手动 new

3.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 moduleProvider 未注册在 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 中导入

八、学习要点总结

核心要点

  1. DI 容器本质:管理所有类实例的公共区域,不是 Docker 容器
  2. 初始化流程:扫描 @Injectable → 分析构造器 → 构建依赖图 → 创建实例
  3. providers 作用:告诉 DI 系统初始化类实例
  4. exports 作用:告诉 NestJS 这个类需要在其他地方使用
  5. imports 作用:导入其他模块,使用其导出的实例
  6. 查找路径:providers → imports → exports

记忆技巧

code
快速记忆:

DI 容器 = 仓库(存实例)

providers = 入库(注册)
exports = 开门(允许取用)
imports = 进货(导入其他模块)
controllers = 取货(获取实例)

查找顺序:
providers → imports → exports

行动建议

code
学习路径:
│
├──  第一阶段:理解概念(1 天)
│   ├── 理解 DI 容器
│   ├── 理解初始化流程
│   └── 理解四大属性作用
│
├──  第二阶段:实践练习(3 天)
│   ├── 创建多模块项目
│   ├── 实现模块间依赖
│   └── 解决依赖注入错误
│
└──  第三阶段:深入应用(持续)
    ├── 理解 DI 系统源码
    ├── 解决复杂依赖关系
    └── 优化模块架构

九、延伸学习资源

官方资源

练习建议

  1. 练习 1:创建一个多模块项目,实现模块间依赖
  2. 练习 2:模拟依赖注入错误,尝试解决
  3. 练习 3:使用 forwardRef 解决循环依赖
  4. 练习 4:实现一个 Shared Module
  5. 练习 5:绘制项目的依赖关系图

延伸思考

code
思考题:
│
├──  DI 容器是如何实现单例模式的?
├──  为什么 providers 不能导入模块?
├──  forwardRef 的原理是什么?
├──  如何设计合理的模块架构?
└──  DI 系统对性能有什么影响?

附录:DI 系统速查表

概念作用关键词
DI 容器管理实例公共区域、大对象
@Injectable标记可注入注册到 DI 容器
providers注册实例告诉 DI 初始化
exports导出实例允许外部使用
imports导入模块使用其他模块实例
查找路径providers → imports依赖查找顺序

笔记整理完成时间:2026-03-07
下一章节预告:NestJS 数据库实战