用于 JavaScript (Node.js) 的依赖注入容器 — Awilix

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

用于 JavaScript (Node.js) 的依赖注入容器 — Awilix



在现代 Node.js 开发中,代码架构的清晰度和可测试性变得至关重要。实现这些目标的关键工具之一就是依赖注入 (Dependency Injection, DI)。Awilix 库为 JavaScript 和 TypeScript 提供了一个强大、高性能且灵活的 DI 容器,特别适合 Node.js 服务器端应用程序。在本文中,我们将详细介绍如何使用 Awilix 来管理依赖关系、改善模块化并简化测试。



什么是依赖注入以及为什么需要容器?



依赖注入是一种设计模式,其中对象从外部获取其依赖项,而不是自己创建它们。这实现了控制反转 (Inversion of Control, IoC) 原则。容器是一种自动化创建和提供这些依赖项的工具。您无需手动创建类实例并将它们相互传递,而是在容器中描述构建规则,容器会自动解析所有依赖链。



使用 DI 容器的主要优势:

  • 降低代码耦合度:模块依赖于抽象,而不是具体实现。
  • 简化测试:在单元测试期间,可以轻松地将真实服务替换为模拟对象 (mock)。
  • 集中管理:所有依赖配置都集中在一个地方,从而简化了重构。
  • 生命周期管理:容器可以控制对象的存活时间——整个应用程序一个实例 (单例) 或每次请求一个新实例。


安装 Awilix



首先,通过 npm 安装该库:

npm install awilix


Awilix 没有外部依赖,并且同时支持 CommonJS 和 ESM 模块。



Awilix 的核心概念



Awilix 围绕几个关键概念构建:

  • Container (容器):存储和提供依赖项的主要对象。
  • Registration (注册):将名称 (令牌) 与工厂、类或值关联起来的过程。
  • Resolver (解析器):决定如何创建或获取依赖项的对象。例如,asClass()、asFunction()、asValue()。
  • Lifetime (生命周期):指定对象将被创建多少次:ScopedLifeTime (每个作用域一次)、SingletonLifeTime (整个生命周期一次) 或 TransientLifeTime (每次都新建)。


使用示例:用户服务



让我们看一个简单的例子。假设我们有一个数据库、一个用户仓库和一个用于业务逻辑的服务。



1. 定义类

// database.jsclass Database {    constructor() {        this.connection = 'Connected to DB';    }    query(sql) {        return `Result for: ${sql}`;    }}

// userRepository.jsclass UserRepository { constructor({ database }) { this.db = database; } findById(id) { return this.db.query(`SELECT * FROM users WHERE id = ${id}`); }}

// userService.jsclass UserService { constructor({ userRepository }) { this.repo = userRepository; } getUser(id) { return this.repo.findById(id); }}


注意构造函数:它们接受一个包含依赖项的对象。这是 Awilix 的标准做法。



2. 配置容器

const { createContainer, asClass, asValue, Lifetime } = require('awilix');

const container = createContainer();

// 注册

推荐