当前位置: 首页 > news >正文

【NestJS】依赖注入:超越自动new的深层解析

NestJS 依赖注入(DI)全解析:不仅仅是 new 一下

你对 NestJS 或 Angular 的依赖注入系统的直觉非常准:

“看起来不过就是自动 new 一下类而已。”

没错,从表面上看确实如此,但 NestJS DI 的底层机制和设计哲学远比这复杂,它不仅仅是自动创建对象,而是一套完整的 对象生命周期管理、依赖解耦和模块化架构系统

下面我从 表象 → 原理 → 设计模式 → 实际威力 四个层次来讲透。


🧩 一、表象层:@Injectable() 只是标记可注入对象

@Injectable()
export class UserService {constructor(private db: DatabaseService) {}
}

看起来,Nest 启动时只是做了几件事:

  1. 检查 UserService 是否带有 @Injectable()
  2. 自动创建它的实例;
  3. 解析构造函数参数;
  4. 把依赖的 DatabaseService 注入进去。

表面上看就是帮你 new UserService(new DatabaseService()),但它背后是一个自动、可扩展、可替换、可分层的对象创建系统


⚙️ 二、原理层:NestJS DI 容器 = IoC + 依赖图解析器

Nest 的 DI 核心是 IoC 容器(Inversion of Control Container)
它本质上是 “对象工厂 + 依赖图解析器”

// 传统写法:
const userService = new UserService(new DatabaseService());// Nest DI:
const userService = container.resolve(UserService);

容器会自动:

  • 扫描所有 @Injectable() 类;
  • 构建依赖图,解析依赖关系;
  • 递归实例化依赖对象;
  • 管理对象生命周期(单例、请求作用域、瞬时);
  • 支持替换依赖(不同环境或 mock)。

这就是“控制反转(IoC)”的真正含义:业务对象不负责创建依赖,由容器统一管理。


🧱 三、设计模式层:DI 是多种经典模式的集合

模式DI 中体现
工厂模式(Factory)容器负责对象创建
单例模式(Singleton)默认 provider 全局单例
策略模式(Strategy)不同 token 提供不同实现
装饰器模式(Decorator)@Injectable()@Module() 保存元信息
依赖反转原则(DIP)上层依赖抽象接口而非具体实现

💡 实例:切换实现而不改业务代码

export abstract class Logger {abstract log(message: string): void;
}@Injectable()
export class ConsoleLogger implements Logger {log(msg: string) { console.log(msg); }
}@Injectable()
export class FileLogger implements Logger {log(msg: string) { writeFileSync('log.txt', msg); }
}// 模块中切换实现:
@Module({providers: [{ provide: Logger, useClass: FileLogger }],
})
export class AppModule {}

业务层依赖 Logger 抽象类,最终实现由模块配置决定。
这就是 依赖反转 + 策略模式 的威力。


🧠 四、实际威力:可扩展、可测试、可替换、可插拔

1️⃣ 可扩展性

模块化系统通过 provider 注入,实现插件式扩展:

@Module({imports: [DatabaseModule, UserModule, AuthModule],
})
export class AppModule {}

模块之间解耦,可随时增删。

2️⃣ 可测试性

单元测试时轻松 mock 依赖,无需改业务代码:

const moduleRef = await Test.createTestingModule({providers: [UserService,{ provide: DatabaseService, useValue: mockDb },],
}).compile();

3️⃣ 可插拔架构

开发支付模块:

export abstract class PaymentProvider {abstract pay(): Promise<void>;
}

不同 app 只需注册不同实现:

{ provide: PaymentProvider, useClass: WechatPay }
{ provide: PaymentProvider, useClass: StripePay }

上层逻辑完全不变。

4️⃣ 生命周期控制

Nest 可控制实例作用域:

Scope描述
DEFAULT全局单例
REQUEST每个请求新实例
TRANSIENT每次注入都新实例

既高效(单例),又能隔离(请求作用域)。


http://www.dtcms.com/a/524694.html

相关文章:

  • 北京网站建设策划建设公司长春建站培训
  • Mac常用软件
  • 【Linux笔记】网络部分——基于Socket套接字实现最简单的HTTP协议服务器
  • Linux基础知识(三、Linux常见操作目录命令)
  • 类似凡科建站的平台手机网站仿站
  • 在网站文字上做笔记设计制作中国第一架飞机的人是
  • C++ 分治 快速选择算法 堆排序 TopK问题 力扣 215. 数组中的第K个最大元素 题解 每日一题
  • 永磁同步电机无速度算法--基于相位超前校正的LESO
  • 动态 静态 网站地图合肥庐阳区建设局网站
  • JavaEE开篇之计算机是如何工作的
  • 基于python机器学习的农产品价格数据分析与预测的可视化系统
  • 如何通过掌纹识别实现Windows工作站安全登录:从技术原理到企业级落地实践
  • 正则表达式全集
  • 中山手机网站制作哪家好网站管理员登陆后缀
  • K8s高可用:四大核心机制解析
  • 1024勋章发文活动
  • 依托金仓数据库的医疗信创多院区实践与 KingbaseES 操作详解
  • Linux---开发工具2
  • GBase安装部署
  • 4A架构解析:业务、数据、应用、技术架构的区别与联系
  • Redisson与Spring提供的RedisTemplate做一个对比
  • 南京做网站公司地点免费ddns域名注册
  • asp网站开发报告酷站是什么网站
  • [服务部署]京东云部署JavaWeb项目
  • 27、LangChain开发框架(四)-- LangChain接入工具基本流程
  • 找人做网站要准备什么九江网站网站建设
  • 帝可得智能售货机系统实战Day1:从环境搭建到区域管理功能落地 (1)
  • 10.2Web Component
  • 有没有做产品团购的网站wordpress文章页禁止右键
  • Nginx 反向代理解析:从原理到生产级配置实战