NestJS中@Injectable装饰器

一、基础定义与核心作用

1.1 什么是@Injectable?

@Injectable() 是 NestJS 依赖注入(Dependency Injection, DI)系统的核心装饰器,用于将类标记为可注入的提供者(Provider)。它告知 NestJS 的 IoC(控制反转)容器:该类需要被实例化并管理其依赖关系。

1.2 核心功能

  • 依赖注入(DI):通过构造函数自动注入依赖项,实现类之间的松耦合。
  • 提供者注册:将类注册到 NestJS 的提供者容器中,使其可在其他组件(如控制器、服务)中被注入和使用。
  • 生命周期管理:结合作用域(Scope)控制实例的创建和销毁时机。

1.3 典型示例

import { Injectable } from '@nestjs/common';@Injectable()
export class LoggerService {log(message: string) {console.log(`[Logger] ${message}`);}
}@Injectable()
export class UserService {constructor(private readonly logger: LoggerService) {}getUser() {this.logger.log('Fetching user...');return { id: 1, name: 'John' };}
}

二、高级特性详解

2.1 作用域(Scope)

NestJS 提供三种作用域,控制提供者实例的生命周期:

2.1.1 DEFAULT(单例)
  • 行为:应用启动时创建一次实例,整个生命周期内复用。
  • 适用场景:无状态服务(如日志服务、配置服务)。
  • 配置
    @Injectable() // 默认即为单例
    export class ConfigService {// 无状态配置逻辑
    }
    
2.1.2 REQUEST
  • 行为:每个 HTTP 请求创建新实例,实例仅在当前请求内有效。
  • 适用场景:需维护请求上下文的服务(如用户会话、请求级缓存)。
  • 配置
    import { Injectable, Scope } from '@nestjs/common';@Injectable({ scope: Scope.REQUEST })
    export class UserSessionService {private userId: string;setUserId(id: string) {this.userId = id;}getUserId() {return this.userId;}
    }
    
2.1.3 TRANSIENT
  • 行为:每次注入时创建新实例。
  • 适用场景:需要新鲜实例的场景(如临时日志记录器)。
  • 配置
    @Injectable({ scope: Scope.TRANSIENT })
    export class TempLoggerService {log(message: string) {console.log(`[TempLog] ${message}`);}
    }
    

2.2 自定义提供者

通过模块的 providers 数组灵活配置依赖:

import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { LoggerService } from './logger.service';@Module({providers: [UserService,{provide: 'CustomLogger',useClass: LoggerService, // 使用已有类},{provide: 'Config',useValue: { apiKey: '123' }, // 静态值},{provide: 'Database',useFactory: () => {// 工厂函数,可依赖其他提供者const config = new ConfigService();return new DatabaseConnection(config);},inject: [ConfigService], // 注入其他提供者},],exports: [UserService, 'CustomLogger'], // 导出供其他模块使用
})
export class AppModule {}

三、常见问题与解决方案

3.1 依赖未解析错误

错误Nest can't resolve dependencies of the UserService (?)
原因:依赖未正确注册到模块的 providers 中。
解决方案

@Module({providers: [UserService, LoggerService], // 确保所有依赖已注册controllers: [UserController],
})
export class UserModule {}

3.2 循环依赖

错误:两个服务相互依赖(A → B → A)。
解决方案

  • 重构代码:将共享逻辑提取到第三方服务。
  • 使用 forwardRef
    @Module({imports: [forwardRef(() => OtherModule)],
    })
    

3.3 作用域冲突

问题:单例服务依赖请求作用域服务。
解决方案

  • 使用 @Inject(CONTEXT)
    import { INJECTABLE_METADATA } from '@nestjs/common';@Injectable()
    export class SingletonService {constructor(@Inject(CONTEXT) private context: any) {}
    }
    

四、与Angular的对比

4.1 相似性

  • DI机制:均使用 @Injectable()@Inject() 装饰器。
  • 模块化:通过模块(Module)组织依赖关系。
  • 作用域:支持类似的作用域配置(如 Angular 的 providedIn)。

4.2 差异

特性NestJSAngular
运行环境Node.js 后端浏览器前端
核心功能HTTP 服务器、微服务、GraphQLSPA 开发、路由、模板引擎
作用域默认值DEFAULT(单例)root(单例)
典型场景API 开发、后端服务客户端应用、组件化开发

五、最佳实践

5.1 模块化组织

  • 按功能划分模块:将相关服务、控制器封装到独立模块。
  • 导出公共服务:通过 exports 暴露公共提供者,避免全局污染。

5.2 作用域选择

  • 优先单例:无状态服务使用默认单例作用域,优化性能。
  • 请求作用域:需维护请求上下文时使用,注意实例创建开销。

5.3 测试策略

  • 模拟依赖:使用 Test.createTestingModule() 模拟服务:
    describe('UserService', () => {let service: UserService;const mockLogger = { log: jest.fn() };beforeEach(async () => {const module: TestingModule = await Test.createTestingModule({providers: [UserService,{ provide: LoggerService, useValue: mockLogger },],}).compile();service = module.get<UserService>(UserService);});
    });
    

六、总结

@Injectable() 是 NestJS 实现依赖注入和 IoC 的基石,通过合理使用其作用域、自定义提供者等功能,可构建出高可维护性、可扩展的后端应用。结合模块化设计和最佳实践,能进一步提升开发效率和代码质量。掌握 @Injectable() 的高级特性(如作用域、自定义提供者)是成为 NestJS 高级开发者的关键一步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/92366.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/92366.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习深度学习】大模型应用落地:微调与RAG的角色与实践

目录 前言 一、微调与RAG&#xff1a;大模型应用落地的两大支柱 1. 微调&#xff08;Fine-tuning&#xff09; 2. RAG&#xff08;Retrieval-Augmented Generation&#xff09; 二、微调可以做什么&#xff1f; 1. 模型自我认知调整 2. 对话风格优化 3. 提升问题理解能…

List、ArrayList 与顺序表

目录 一、List 介绍 二、线性表 三、自己实现 ArrayList 3.1 显示元素 3.2 增 3.2.1 默认在数组后面新增元素 3.2.2 在指定位置中新增元素 3.3 查 3.4 取值 3.5 改 3.5.1 把 pos 位置的元素修改成 value 3.5.2 删除某个元素 3.5.3 清空 四、认识 ArrayList 4.0 说…

Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现各类垃圾的分类检测识别(C#代码UI界面版)

Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现各类垃圾的分类检测识别&#xff08;C#代码UI界面版&#xff09;工业相机使用YoloV8模型实现各类垃圾的分类检测识别工业相机通过YoloV8模型实现各类垃圾的分类检测识别的技术背景在相机SDK中获取图像转换图像的代码分…

EasyExcel高效工具类:简化Excel导入导出,支持多Sheet与枚举转换

文章目录前言一、依赖坐标二、工具类&#xff1a;ExcelUtil三、测试1.实体类2.前置操作3.单Sheet导出4.单Sheet导入5.多Sheet导出6.多Sheet导入7.完整代码四、扩展&#xff1a;自定义注解实现枚举类型转换1.枚举接口2.枚举类3.注解4.转换类5.使用示例6.测试总结前言 在现代应用…

技术速递|GitHub Copilot for Eclipse 迈出重要一步

我们非常高兴地宣布&#xff1a;2025 年 7 月 22 日&#xff0c;GitHub Copilot for Eclipse 又迈出了重要一步&#xff0c;Eclipse 变得更智能、更快捷&#xff0c;而且与 Eclipse 的集成也更无缝了&#xff01;这是继新功能上线以来&#xff0c;又一次质的提升。 &#x1f…

Coze Loop:开源智能体自动化流程编排平台原理与实践

项目简介 Coze Loop 是 Coze 团队开源的智能体自动化流程编排平台。它以“Loop”为核心概念,支持开发者通过低代码/可视化方式,将多种 AI Agent、插件、API、数据流等灵活编排为自动化工作流,实现复杂的智能体协作、任务自动化和多模态数据处理。Coze Loop 适用于企业自动化…

[GESP202309 四级] 2023年9月GESP C++四级上机题题解,附带讲解视频!

本文为2023年9月GESP C四级的上机题目的详细题解&#xff01;觉得写的不错或者有帮助可以点个赞啦。 目录 题目一讲解视频: 题目二讲解视频: 题目一:进制转换 解题思路: 代码(C): 题目二:变长编码 解题思路: 代码(C): 题目一讲解视频: 2023年9月GESP C四级上机题一题目…

【AI编程工具IDE/CLI/插件专栏】-国外IDE与Cursor能力对比

AI编程专栏(二) - Cursor 深度使用指南 Cursor 深度使用指南(二) - 新能力使用教程 从Trae 2.0与CodeBuddy IDE发布&#xff0c;谈大厂布局IDE 如何选择AI IDE&#xff1f;对比Cursor分析功能差异 AI编程工具IDE/CLI/插件专栏-热门AI编程CLI初识与IDE对 前面文章介绍过了国…

word2vector细致分解(CBOW, SKIP_GRAM, 层次soft Max, 负采样)

1 前世今生&#xff1a;NGRAM NGRAM&#xff1a;将词当成一个离散的单元&#xff08;因此存在一定的局限性&#xff0c;没有考虑到词与词之间的关系&#xff09; neural network language model&#xff1a;只能处理定长序列&#xff0c;训练慢。使用RNN之后有所改善 2 两种训…

Elasticsearch向量库

在Elasticsearch&#xff08;ES&#xff09;最新版本&#xff08;目前8.x系列&#xff09;中&#xff0c;无需额外的“embedding插件”&#xff0c;因为ES从7.14版本开始就原生支持向量数据类型&#xff08;dense_vector&#xff09; 和向量搜索能力&#xff0c;可直接作为向量…

嵌入式学习的第四十四天-ARM

一、ARM内核基础知识1.ALU算术逻辑单元&#xff1b;完成运算的电路2.通用寄存器&#xff1a;R0~R15R13&#xff08;SP&#xff09;&#xff1a;栈指针寄存器&#xff1a;指向栈的指针&#xff08;指向正确的位置&#xff09;&#xff0c;为了保护现场 R14&#xff08;LR…

QML开发:QML中的基本元素

文章目录一、概述二、常用基本元素2.1 基础视觉元素&#xff08;常用于布局和显示&#xff09;2.1.1 元素 Item 的介绍和使用2.1.2 元素 Rectangle 的介绍和使用2.1.3 元素 Image 的介绍和使用2.1.4 元素 Text 的介绍和使用2.2 交互元素&#xff08;用于接收用户操作&#xff0…

Spring AI 项目实战(二十二):Spring Boot + AI +DeepSeek实现智能合同数据问答助手​(附完整源码)

系列文章 序号 文章名称 1 Spring AI 项目实战(一):Spring AI 核心模块入门 2 Spring AI 项目实战(二):Spring Boot + AI + DeepSeek 深度实战(附完整源码) 3 Spring AI 项目实战(三):Spring Boot + AI + DeepSeek 打造智能客服系统(附完整源码) 4

从 0 到 1 创建 InfluxDB 3 表:标签、字段、命名规范一篇讲透

前言 在使用 InfluxDB 3 存储时序数据时,表的设计堪比盖房子打地基,地基打歪,数据“塌方”指日可待。InfluxDB 虽然不是传统意义上的关系型数据库,但它有自己的一套“审美”:标签(Tags)和字段(Fields)是它的双核心,谁先谁后,关系重大,顺序写错,查询性能立马打折。…

[sqlserver] 分析SQL Server中执行效率较低的SQL语句

查询性能分析较低的SQL语句 -- 查询性能分析 SELECT TOP 50qs.creation_time AS [编译时间],qs.last_execution_time AS [最后执行时间],qs.execution_count AS [执行次数],qs.total_worker_time/1000 AS [CPU总时间(ms)],qs.total_elapsed_time/1000 AS [总耗时(ms)],(qs.tota…

SmartX 用户建云实践|宝信软件:搭建“双架构”私有云平台,灵活满足多种业务需求

上海宝信软件股份有限公司&#xff08;以下简称宝信软件&#xff09;系中国宝武实际控制、宝钢股份控股的上市软件企业&#xff0c;是中国领先的工业软件行业应用解决方案和服务提供商&#xff0c;为宝武集团提供整体 IT 基础架构解决方案与服务。为统一管理宝武集团旗下分散在…

应用科普 | 漫谈6G通信的未来

【摘要前言】2019年推出的5G无线通信将移动设备的性能提升到了一个新的水平。首批应用利用5G提供移动宽带&#xff0c;使消费者能够以远超以往的速度进行流媒体传输、游戏和连接。随着技术的成熟&#xff0c;它已成为物联网的关键组成部分&#xff0c;将机器汇集到一个全球网络…

从零开始用 Eclipse 写第一个 Java 程序:HelloWorld 全流程 + 避坑指南

对于 Java 初学者来说&#xff0c;第一次用 Eclipse 写程序往往会手足无措 —— 找不到新建项目的入口、不知道包和类该怎么命名、运行时控制台突然消失…… 别慌&#xff01;本文以最经典的 “HelloWorld” 为例&#xff0c;手把手带你走完从 Eclipse 项目创建到程序运行的完整…

NVIDIA Isaac GR00T N1.5 源码剖析与复现

​ 0. 前言 2025.6.11 NVIDIA Isaac GR00T N1 进化&#xff0c;英伟达发布了NVIDIA Isaac GR00T N1.5模型&#xff0c;效果比原先提高了不少&#xff0c;故来复现一下&#xff0c;看看能否应用于我的项目中&#xff1a; 代码页 项目页 模型页 ​ 以下是使用 GR00T N1.5 的一般…

手把手教你驯服Apache IoTDB时序数据库,开启时序数据管理新征程!

手把手教你驯服Apache IoTDB&#xff0c;开启时序数据管理新征程&#xff01; 本文是一篇幽默风趣的 Apache IoTDB 时序数据库安装使用教程。从 “这东西能不能吃” 的灵魂拷问切入&#xff0c;先科普 IoTDB 的 “真实身份”—— 一款专为时序数据设计的数据库利器&#xff0c;…