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
英文地址,請注明出處:http://en.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;…