[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmodule":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmodule":1827,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmodule":1853},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":14,"pinned":15,"draft":15,"body":16,"seo":1823,"stem":1824,"id":1825,"extension":1826},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmodule","模块系统与依赖注入","@Module 组织控制器与 Provider；依赖注入由 IoC 容器管理。见 导读、基础。","技能小册",[12,13],"nestjs","module","2022-06-15",false,{"type":17,"value":18,"toc":1815},"minimark",[19,22,46,54,65,70,156,359,366,376,448,454,458,461,526,541,545,548,794,806,810,813,817,827,880,892,956,960,963,1038,1245,1249,1258,1368,1372,1379,1497,1503,1507,1510,1566,1576,1579,1596,1610,1613,1664,1716,1750,1753,1757,1760,1811],[20,21,8],"h1",{"id":8},[23,24,25,29,30,34,35,40,41,45],"p",{},[26,27,28],"code",{},"@Module"," 组织控制器与 Provider；",[31,32,33],"strong",{},"依赖注入","由 IoC 容器管理。见 ",[36,37,39],"a",{"href":38},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs","导读","、",[36,42,44],{"href":43},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fbase","基础","。",[47,48,50,51,53],"h3",{"id":49},"一模块module","一、模块（",[26,52,28],{},"）",[23,55,56,57,60,61,64],{},"模块是用 ",[26,58,59],{},"@Module()"," 装饰器声明的类，它将一组控制器、提供者等组织在一起。每个 Nest 应用至少有一个根模块（",[26,62,63],{},"AppModule","）。",[66,67,69],"h4",{"id":68},"_1-4-个核心属性","1. 4 个核心属性",[71,72,73,89],"table",{},[74,75,76],"thead",{},[77,78,79,83,86],"tr",{},[80,81,82],"th",{},"属性",[80,84,85],{},"类型",[80,87,88],{},"描述",[90,91,92,108,123,138],"tbody",{},[77,93,94,100,105],{},[95,96,97],"td",{},[26,98,99],{},"imports",[95,101,102],{},[26,103,104],{},"Array\u003CModuleType>",[95,106,107],{},"导入其他模块中导出的提供者（如服务、存储库）",[77,109,110,115,120],{},[95,111,112],{},[26,113,114],{},"controllers",[95,116,117],{},[26,118,119],{},"Array\u003CControllerType>",[95,121,122],{},"该模块中需要实例化的控制器类",[77,124,125,130,135],{},[95,126,127],{},[26,128,129],{},"providers",[95,131,132],{},[26,133,134],{},"Array\u003CProviderType>",[95,136,137],{},"该模块中可注入的服务、工厂等提供者",[77,139,140,145,150],{},[95,141,142],{},[26,143,144],{},"exports",[95,146,147],{},[26,148,149],{},"Array\u003Cstring | symbol | ProviderType>",[95,151,152,153,155],{},"导出本模块的提供者，供其他模块使用（需在 ",[26,154,99],{}," 中导入本模块）",[157,158,163],"pre",{"className":159,"code":160,"language":161,"meta":162,"style":162},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import { Module } from \"@nestjs\u002Fcommon\";\nimport { UsersController } from \".\u002Fusers.controller\";\nimport { UsersService } from \".\u002Fusers.service\";\n\n@Module({\n  imports: [], \u002F\u002F 可导入其他模块\n  controllers: [UsersController],\n  providers: [UsersService],\n  exports: [UsersService], \u002F\u002F 允许其他模块使用 UsersService\n})\nexport class UsersModule {}\n","ts","",[26,164,165,202,225,248,255,271,291,305,318,333,342],{"__ignoreMap":162},[166,167,170,174,178,182,185,188,192,196,199],"span",{"class":168,"line":169},"line",1,[166,171,173],{"class":172},"sVHd0","import",[166,175,177],{"class":176},"sP7_E"," {",[166,179,181],{"class":180},"su5hD"," Module",[166,183,184],{"class":176}," }",[166,186,187],{"class":172}," from",[166,189,191],{"class":190},"sjJ54"," \"",[166,193,195],{"class":194},"s_sjI","@nestjs\u002Fcommon",[166,197,198],{"class":190},"\"",[166,200,201],{"class":176},";\n",[166,203,205,207,209,212,214,216,218,221,223],{"class":168,"line":204},2,[166,206,173],{"class":172},[166,208,177],{"class":176},[166,210,211],{"class":180}," UsersController",[166,213,184],{"class":176},[166,215,187],{"class":172},[166,217,191],{"class":190},[166,219,220],{"class":194},".\u002Fusers.controller",[166,222,198],{"class":190},[166,224,201],{"class":176},[166,226,228,230,232,235,237,239,241,244,246],{"class":168,"line":227},3,[166,229,173],{"class":172},[166,231,177],{"class":176},[166,233,234],{"class":180}," UsersService",[166,236,184],{"class":176},[166,238,187],{"class":172},[166,240,191],{"class":190},[166,242,243],{"class":194},".\u002Fusers.service",[166,245,198],{"class":190},[166,247,201],{"class":176},[166,249,251],{"class":168,"line":250},4,[166,252,254],{"emptyLinePlaceholder":253},true,"\n",[166,256,258,261,265,268],{"class":168,"line":257},5,[166,259,260],{"class":176},"@",[166,262,264],{"class":263},"sGLFI","Module",[166,266,267],{"class":180},"(",[166,269,270],{"class":176},"{\n",[166,272,274,278,281,284,287],{"class":168,"line":273},6,[166,275,277],{"class":276},"skxfh","  imports",[166,279,280],{"class":176},":",[166,282,283],{"class":180}," []",[166,285,286],{"class":176},",",[166,288,290],{"class":289},"sutJx"," \u002F\u002F 可导入其他模块\n",[166,292,294,297,299,302],{"class":168,"line":293},7,[166,295,296],{"class":276},"  controllers",[166,298,280],{"class":176},[166,300,301],{"class":180}," [UsersController]",[166,303,304],{"class":176},",\n",[166,306,308,311,313,316],{"class":168,"line":307},8,[166,309,310],{"class":276},"  providers",[166,312,280],{"class":176},[166,314,315],{"class":180}," [UsersService]",[166,317,304],{"class":176},[166,319,321,324,326,328,330],{"class":168,"line":320},9,[166,322,323],{"class":276},"  exports",[166,325,280],{"class":176},[166,327,315],{"class":180},[166,329,286],{"class":176},[166,331,332],{"class":289}," \u002F\u002F 允许其他模块使用 UsersService\n",[166,334,336,339],{"class":168,"line":335},10,[166,337,338],{"class":176},"}",[166,340,341],{"class":180},")\n",[166,343,345,348,352,356],{"class":168,"line":344},11,[166,346,347],{"class":172},"export",[166,349,351],{"class":350},"sbsja"," class",[166,353,355],{"class":354},"sbgvK"," UsersModule",[166,357,358],{"class":176}," {}\n",[66,360,362,363,53],{"id":361},"_2-全局模块global","2. 全局模块（",[26,364,365],{},"@Global",[23,367,368,369,372,373,375],{},"使用 ",[26,370,371],{},"@Global()"," 装饰器的模块称为全局模块，其导出的提供者可在所有模块中直接注入，无需在 ",[26,374,99],{}," 中声明。",[157,377,379],{"className":159,"code":378,"language":161,"meta":162,"style":162},"@Global()\n@Module({\n  providers: [ConfigService],\n  exports: [ConfigService],\n})\nexport class CommonModule {}\n\n\u002F\u002F 任意模块中都可以直接注入 ConfigService\n",[26,380,381,391,401,412,422,428,439,443],{"__ignoreMap":162},[166,382,383,385,388],{"class":168,"line":169},[166,384,260],{"class":176},[166,386,387],{"class":263},"Global",[166,389,390],{"class":180},"()\n",[166,392,393,395,397,399],{"class":168,"line":204},[166,394,260],{"class":176},[166,396,264],{"class":263},[166,398,267],{"class":180},[166,400,270],{"class":176},[166,402,403,405,407,410],{"class":168,"line":227},[166,404,310],{"class":276},[166,406,280],{"class":176},[166,408,409],{"class":180}," [ConfigService]",[166,411,304],{"class":176},[166,413,414,416,418,420],{"class":168,"line":250},[166,415,323],{"class":276},[166,417,280],{"class":176},[166,419,409],{"class":180},[166,421,304],{"class":176},[166,423,424,426],{"class":168,"line":257},[166,425,338],{"class":176},[166,427,341],{"class":180},[166,429,430,432,434,437],{"class":168,"line":273},[166,431,347],{"class":172},[166,433,351],{"class":350},[166,435,436],{"class":354}," CommonModule",[166,438,358],{"class":176},[166,440,441],{"class":168,"line":293},[166,442,254],{"emptyLinePlaceholder":253},[166,444,445],{"class":168,"line":307},[166,446,447],{"class":289},"\u002F\u002F 任意模块中都可以直接注入 ConfigService\n",[23,449,450,453],{},[31,451,452],{},"适用场景","：通用基础设施服务（配置模块、日志模块、数据库连接池等），避免在每个模块中重复导入。",[66,455,457],{"id":456},"_3-模块重导出","3. 模块重导出",[23,459,460],{},"模块可以重新导出其他模块的提供者，实现聚合导出。",[157,462,464],{"className":159,"code":463,"language":161,"meta":162,"style":162},"@Module({\n  imports: [DatabaseModule, CacheModule],\n  exports: [DatabaseModule, CacheModule], \u002F\u002F 将这两个模块的提供者一并导出\n})\nexport class DataAccessModule {}\n",[26,465,466,476,492,509,515],{"__ignoreMap":162},[166,467,468,470,472,474],{"class":168,"line":169},[166,469,260],{"class":176},[166,471,264],{"class":263},[166,473,267],{"class":180},[166,475,270],{"class":176},[166,477,478,480,482,485,487,490],{"class":168,"line":204},[166,479,277],{"class":276},[166,481,280],{"class":176},[166,483,484],{"class":180}," [DatabaseModule",[166,486,286],{"class":176},[166,488,489],{"class":180}," CacheModule]",[166,491,304],{"class":176},[166,493,494,496,498,500,502,504,506],{"class":168,"line":227},[166,495,323],{"class":276},[166,497,280],{"class":176},[166,499,484],{"class":180},[166,501,286],{"class":176},[166,503,489],{"class":180},[166,505,286],{"class":176},[166,507,508],{"class":289}," \u002F\u002F 将这两个模块的提供者一并导出\n",[166,510,511,513],{"class":168,"line":250},[166,512,338],{"class":176},[166,514,341],{"class":180},[166,516,517,519,521,524],{"class":168,"line":257},[166,518,347],{"class":172},[166,520,351],{"class":350},[166,522,523],{"class":354}," DataAccessModule",[166,525,358],{"class":176},[23,527,528,529,532,533,536,537,540],{},"这样其他模块只需导入 ",[26,530,531],{},"DataAccessModule"," 即可获得 ",[26,534,535],{},"DatabaseModule"," 和 ",[26,538,539],{},"CacheModule"," 的所有导出。",[66,542,544],{"id":543},"_4-动态模块dynamicmodule","4. 动态模块（DynamicModule）",[23,546,547],{},"动态模块允许在导入时传递配置参数，从而动态生成模块的定义。",[157,549,551],{"className":159,"code":550,"language":161,"meta":162,"style":162},"export class ConfigModule {\n  static forRoot(options: ConfigOptions): DynamicModule {\n    return {\n      module: ConfigModule,\n      providers: [\n        {\n          provide: \"CONFIG_OPTIONS\",\n          useValue: options,\n        },\n        ConfigService,\n      ],\n      exports: [ConfigService],\n    };\n  }\n}\n\n\u002F\u002F 导入时\n@Module({\n  imports: [ConfigModule.forRoot({ path: \".\u002Fconfig.json\" })],\n})\nexport class AppModule {}\n",[26,552,553,565,596,603,614,624,629,645,657,662,669,676,695,701,707,713,718,724,735,775,782],{"__ignoreMap":162},[166,554,555,557,559,562],{"class":168,"line":169},[166,556,347],{"class":172},[166,558,351],{"class":350},[166,560,561],{"class":354}," ConfigModule",[166,563,564],{"class":176}," {\n",[166,566,567,570,574,576,580,583,586,589,591,594],{"class":168,"line":204},[166,568,569],{"class":350},"  static",[166,571,573],{"class":572},"sVXei"," forRoot",[166,575,267],{"class":176},[166,577,579],{"class":578},"s99_P","options",[166,581,280],{"class":582},"smGrS",[166,584,585],{"class":354}," ConfigOptions",[166,587,588],{"class":176},")",[166,590,280],{"class":582},[166,592,593],{"class":354}," DynamicModule",[166,595,564],{"class":176},[166,597,598,601],{"class":168,"line":227},[166,599,600],{"class":172},"    return",[166,602,564],{"class":176},[166,604,605,608,610,612],{"class":168,"line":250},[166,606,607],{"class":276},"      module",[166,609,280],{"class":176},[166,611,561],{"class":180},[166,613,304],{"class":176},[166,615,616,619,621],{"class":168,"line":257},[166,617,618],{"class":276},"      providers",[166,620,280],{"class":176},[166,622,623],{"class":276}," [\n",[166,625,626],{"class":168,"line":273},[166,627,628],{"class":176},"        {\n",[166,630,631,634,636,638,641,643],{"class":168,"line":293},[166,632,633],{"class":276},"          provide",[166,635,280],{"class":176},[166,637,191],{"class":190},[166,639,640],{"class":194},"CONFIG_OPTIONS",[166,642,198],{"class":190},[166,644,304],{"class":176},[166,646,647,650,652,655],{"class":168,"line":307},[166,648,649],{"class":276},"          useValue",[166,651,280],{"class":176},[166,653,654],{"class":180}," options",[166,656,304],{"class":176},[166,658,659],{"class":168,"line":320},[166,660,661],{"class":176},"        },\n",[166,663,664,667],{"class":168,"line":335},[166,665,666],{"class":180},"        ConfigService",[166,668,304],{"class":176},[166,670,671,674],{"class":168,"line":344},[166,672,673],{"class":276},"      ]",[166,675,304],{"class":176},[166,677,679,682,684,687,690,693],{"class":168,"line":678},12,[166,680,681],{"class":276},"      exports",[166,683,280],{"class":176},[166,685,686],{"class":276}," [",[166,688,689],{"class":180},"ConfigService",[166,691,692],{"class":276},"]",[166,694,304],{"class":176},[166,696,698],{"class":168,"line":697},13,[166,699,700],{"class":176},"    };\n",[166,702,704],{"class":168,"line":703},14,[166,705,706],{"class":176},"  }\n",[166,708,710],{"class":168,"line":709},15,[166,711,712],{"class":176},"}\n",[166,714,716],{"class":168,"line":715},16,[166,717,254],{"emptyLinePlaceholder":253},[166,719,721],{"class":168,"line":720},17,[166,722,723],{"class":289},"\u002F\u002F 导入时\n",[166,725,727,729,731,733],{"class":168,"line":726},18,[166,728,260],{"class":176},[166,730,264],{"class":263},[166,732,267],{"class":180},[166,734,270],{"class":176},[166,736,738,740,742,745,748,751,753,756,759,761,763,766,768,770,773],{"class":168,"line":737},19,[166,739,277],{"class":276},[166,741,280],{"class":176},[166,743,744],{"class":180}," [ConfigModule",[166,746,747],{"class":176},".",[166,749,750],{"class":263},"forRoot",[166,752,267],{"class":180},[166,754,755],{"class":176},"{",[166,757,758],{"class":276}," path",[166,760,280],{"class":176},[166,762,191],{"class":190},[166,764,765],{"class":194},".\u002Fconfig.json",[166,767,198],{"class":190},[166,769,184],{"class":176},[166,771,772],{"class":180},")]",[166,774,304],{"class":176},[166,776,778,780],{"class":168,"line":777},20,[166,779,338],{"class":176},[166,781,341],{"class":180},[166,783,785,787,789,792],{"class":168,"line":784},21,[166,786,347],{"class":172},[166,788,351],{"class":350},[166,790,791],{"class":354}," AppModule",[166,793,358],{"class":176},[23,795,796,797,40,799,40,802,805],{},"常见的动态模块方法命名有：",[26,798,750],{},[26,800,801],{},"forFeature",[26,803,804],{},"register"," 等（如 TypeORM、Mongoose 模块）。",[47,807,809],{"id":808},"二依赖注入di","二、依赖注入（DI）",[23,811,812],{},"NestJS 使用 IoC 容器管理提供者的生命周期和依赖关系。",[66,814,816],{"id":815},"_1-构造函数注入推荐-vs-属性注入","1. 构造函数注入（推荐） vs 属性注入",[818,819,820],"ul",{},[821,822,823,826],"li",{},[31,824,825],{},"构造函数注入","：通过构造函数的参数声明依赖，清晰且易于测试。",[157,828,830],{"className":159,"code":829,"language":161,"meta":162,"style":162},"@Injectable()\nexport class UsersService {\n  constructor(private readonly userRepository: UserRepository) {}\n}\n",[26,831,832,841,851,876],{"__ignoreMap":162},[166,833,834,836,839],{"class":168,"line":169},[166,835,260],{"class":176},[166,837,838],{"class":263},"Injectable",[166,840,390],{"class":180},[166,842,843,845,847,849],{"class":168,"line":204},[166,844,347],{"class":172},[166,846,351],{"class":350},[166,848,234],{"class":354},[166,850,564],{"class":176},[166,852,853,856,858,861,864,867,869,872,874],{"class":168,"line":227},[166,854,855],{"class":350},"  constructor",[166,857,267],{"class":176},[166,859,860],{"class":350},"private",[166,862,863],{"class":350}," readonly",[166,865,866],{"class":578}," userRepository",[166,868,280],{"class":582},[166,870,871],{"class":354}," UserRepository",[166,873,588],{"class":176},[166,875,358],{"class":176},[166,877,878],{"class":168,"line":250},[166,879,712],{"class":176},[818,881,882],{},[821,883,884,887,888,891],{},[31,885,886],{},"属性注入","：使用 ",[26,889,890],{},"@Inject()"," 装饰器直接注入到属性，适用于可选依赖或基类场景。",[157,893,895],{"className":159,"code":894,"language":161,"meta":162,"style":162},"@Injectable()\nexport class UsersService {\n  @Inject(\"CONNECTION\")\n  private readonly connection: Connection;\n}\n",[26,896,897,905,915,934,952],{"__ignoreMap":162},[166,898,899,901,903],{"class":168,"line":169},[166,900,260],{"class":176},[166,902,838],{"class":263},[166,904,390],{"class":180},[166,906,907,909,911,913],{"class":168,"line":204},[166,908,347],{"class":172},[166,910,351],{"class":350},[166,912,234],{"class":354},[166,914,564],{"class":176},[166,916,917,920,923,925,927,930,932],{"class":168,"line":227},[166,918,919],{"class":176},"  @",[166,921,922],{"class":263},"Inject",[166,924,267],{"class":180},[166,926,198],{"class":190},[166,928,929],{"class":194},"CONNECTION",[166,931,198],{"class":190},[166,933,341],{"class":180},[166,935,936,939,941,945,947,950],{"class":168,"line":250},[166,937,938],{"class":350},"  private",[166,940,863],{"class":350},[166,942,944],{"class":943},"sucvu"," connection",[166,946,280],{"class":582},[166,948,949],{"class":354}," Connection",[166,951,201],{"class":176},[166,953,954],{"class":168,"line":257},[166,955,712],{"class":176},[66,957,959],{"id":958},"_2-自定义提供者","2. 自定义提供者",[23,961,962],{},"Nest 提供多种方式定义提供者，超越简单的类注入。",[71,964,965,976],{},[74,966,967],{},[77,968,969,971,973],{},[80,970,85],{},[80,972,88],{},[80,974,975],{},"示例",[90,977,978,993,1008,1023],{},[77,979,980,985,988],{},[95,981,982],{},[26,983,984],{},"useClass",[95,986,987],{},"指定替代类",[95,989,990],{},[26,991,992],{},"{ provide: Logger, useClass: FileLogger }",[77,994,995,1000,1003],{},[95,996,997],{},[26,998,999],{},"useValue",[95,1001,1002],{},"注入常量\u002F对象",[95,1004,1005],{},[26,1006,1007],{},"{ provide: 'PORT', useValue: 3000 }",[77,1009,1010,1015,1018],{},[95,1011,1012],{},[26,1013,1014],{},"useFactory",[95,1016,1017],{},"工厂函数，可注入其他提供者",[95,1019,1020],{},[26,1021,1022],{},"{ provide: 'DB', useFactory: (config) => new DB(config), inject: [ConfigService] }",[77,1024,1025,1030,1033],{},[95,1026,1027],{},[26,1028,1029],{},"useExisting",[95,1031,1032],{},"别名（用于重新映射提供者）",[95,1034,1035],{},[26,1036,1037],{},"{ provide: MyService, useExisting: BetterService }",[157,1039,1041],{"className":159,"code":1040,"language":161,"meta":162,"style":162},"@Module({\n  providers: [\n    { provide: \"DB_NAME\", useValue: \"postgres\" },\n    {\n      provide: \"CONNECTION\",\n      useFactory: (dbName: string) => createConnection(dbName),\n      inject: [\"DB_NAME\"],\n    },\n    { provide: Logger, useClass: FileLogger },\n    { provide: OriginalService, useExisting: EnhancedService }, \u002F\u002F 别名\n  ],\n})\nexport class AppModule {}\n",[26,1042,1043,1053,1061,1095,1100,1115,1147,1166,1171,1195,1222,1229,1235],{"__ignoreMap":162},[166,1044,1045,1047,1049,1051],{"class":168,"line":169},[166,1046,260],{"class":176},[166,1048,264],{"class":263},[166,1050,267],{"class":180},[166,1052,270],{"class":176},[166,1054,1055,1057,1059],{"class":168,"line":204},[166,1056,310],{"class":276},[166,1058,280],{"class":176},[166,1060,623],{"class":180},[166,1062,1063,1066,1069,1071,1073,1076,1078,1080,1083,1085,1087,1090,1092],{"class":168,"line":227},[166,1064,1065],{"class":176},"    {",[166,1067,1068],{"class":276}," provide",[166,1070,280],{"class":176},[166,1072,191],{"class":190},[166,1074,1075],{"class":194},"DB_NAME",[166,1077,198],{"class":190},[166,1079,286],{"class":176},[166,1081,1082],{"class":276}," useValue",[166,1084,280],{"class":176},[166,1086,191],{"class":190},[166,1088,1089],{"class":194},"postgres",[166,1091,198],{"class":190},[166,1093,1094],{"class":176}," },\n",[166,1096,1097],{"class":168,"line":250},[166,1098,1099],{"class":176},"    {\n",[166,1101,1102,1105,1107,1109,1111,1113],{"class":168,"line":257},[166,1103,1104],{"class":276},"      provide",[166,1106,280],{"class":176},[166,1108,191],{"class":190},[166,1110,929],{"class":194},[166,1112,198],{"class":190},[166,1114,304],{"class":176},[166,1116,1117,1120,1122,1125,1128,1130,1134,1136,1139,1142,1145],{"class":168,"line":273},[166,1118,1119],{"class":263},"      useFactory",[166,1121,280],{"class":176},[166,1123,1124],{"class":176}," (",[166,1126,1127],{"class":578},"dbName",[166,1129,280],{"class":582},[166,1131,1133],{"class":1132},"sZMiF"," string",[166,1135,588],{"class":176},[166,1137,1138],{"class":350}," =>",[166,1140,1141],{"class":263}," createConnection",[166,1143,1144],{"class":180},"(dbName)",[166,1146,304],{"class":176},[166,1148,1149,1152,1154,1156,1158,1160,1162,1164],{"class":168,"line":293},[166,1150,1151],{"class":276},"      inject",[166,1153,280],{"class":176},[166,1155,686],{"class":180},[166,1157,198],{"class":190},[166,1159,1075],{"class":194},[166,1161,198],{"class":190},[166,1163,692],{"class":180},[166,1165,304],{"class":176},[166,1167,1168],{"class":168,"line":307},[166,1169,1170],{"class":176},"    },\n",[166,1172,1173,1175,1177,1179,1182,1184,1187,1189,1192],{"class":168,"line":320},[166,1174,1065],{"class":176},[166,1176,1068],{"class":276},[166,1178,280],{"class":176},[166,1180,1181],{"class":180}," Logger",[166,1183,286],{"class":176},[166,1185,1186],{"class":276}," useClass",[166,1188,280],{"class":176},[166,1190,1191],{"class":180}," FileLogger ",[166,1193,1194],{"class":176},"},\n",[166,1196,1197,1199,1201,1203,1206,1208,1211,1213,1216,1219],{"class":168,"line":335},[166,1198,1065],{"class":176},[166,1200,1068],{"class":276},[166,1202,280],{"class":176},[166,1204,1205],{"class":180}," OriginalService",[166,1207,286],{"class":176},[166,1209,1210],{"class":276}," useExisting",[166,1212,280],{"class":176},[166,1214,1215],{"class":180}," EnhancedService ",[166,1217,1218],{"class":176},"},",[166,1220,1221],{"class":289}," \u002F\u002F 别名\n",[166,1223,1224,1227],{"class":168,"line":344},[166,1225,1226],{"class":180},"  ]",[166,1228,304],{"class":176},[166,1230,1231,1233],{"class":168,"line":678},[166,1232,338],{"class":176},[166,1234,341],{"class":180},[166,1236,1237,1239,1241,1243],{"class":168,"line":697},[166,1238,347],{"class":172},[166,1240,351],{"class":350},[166,1242,791],{"class":354},[166,1244,358],{"class":176},[66,1246,1248],{"id":1247},"_3-异步提供者","3. 异步提供者",[23,1250,1251,1253,1254,1257],{},[26,1252,1014],{}," 可以返回 ",[26,1255,1256],{},"Promise","，使提供者异步创建。其他依赖该提供者的服务会等待其解析完成。",[157,1259,1261],{"className":159,"code":1260,"language":161,"meta":162,"style":162},"{\n  provide: 'ASYNC_DB',\n  useFactory: async (config: ConfigService) => {\n    const connection = await createDatabaseConnection(config);\n    return connection;\n  },\n  inject: [ConfigService],\n}\n",[26,1262,1263,1267,1285,1311,1336,1344,1349,1364],{"__ignoreMap":162},[166,1264,1265],{"class":168,"line":169},[166,1266,270],{"class":176},[166,1268,1269,1272,1274,1277,1280,1283],{"class":168,"line":204},[166,1270,1271],{"class":354},"  provide",[166,1273,280],{"class":176},[166,1275,1276],{"class":190}," '",[166,1278,1279],{"class":194},"ASYNC_DB",[166,1281,1282],{"class":190},"'",[166,1284,304],{"class":176},[166,1286,1287,1290,1292,1295,1297,1300,1302,1305,1307,1309],{"class":168,"line":227},[166,1288,1289],{"class":354},"  useFactory",[166,1291,280],{"class":176},[166,1293,1294],{"class":350}," async",[166,1296,1124],{"class":176},[166,1298,1299],{"class":578},"config",[166,1301,280],{"class":582},[166,1303,1304],{"class":354}," ConfigService",[166,1306,588],{"class":176},[166,1308,1138],{"class":350},[166,1310,564],{"class":176},[166,1312,1313,1316,1319,1322,1325,1328,1330,1332,1334],{"class":168,"line":250},[166,1314,1315],{"class":350},"    const",[166,1317,944],{"class":1318},"s_hVV",[166,1320,1321],{"class":582}," =",[166,1323,1324],{"class":172}," await",[166,1326,1327],{"class":263}," createDatabaseConnection",[166,1329,267],{"class":276},[166,1331,1299],{"class":180},[166,1333,588],{"class":276},[166,1335,201],{"class":176},[166,1337,1338,1340,1342],{"class":168,"line":257},[166,1339,600],{"class":172},[166,1341,944],{"class":180},[166,1343,201],{"class":176},[166,1345,1346],{"class":168,"line":273},[166,1347,1348],{"class":176},"  },\n",[166,1350,1351,1354,1356,1358,1360,1362],{"class":168,"line":293},[166,1352,1353],{"class":354},"  inject",[166,1355,280],{"class":176},[166,1357,686],{"class":276},[166,1359,689],{"class":180},[166,1361,692],{"class":276},[166,1363,304],{"class":176},[166,1365,1366],{"class":168,"line":307},[166,1367,712],{"class":176},[66,1369,1371],{"id":1370},"_4-循环依赖解决方案","4. 循环依赖解决方案",[23,1373,1374,1375,1378],{},"当两个类互相依赖时，Nest 无法决定实例化顺序。解决方案：使用 ",[26,1376,1377],{},"forwardRef()"," 函数。",[157,1380,1382],{"className":159,"code":1381,"language":161,"meta":162,"style":162},"@Injectable()\nexport class ServiceA {\n  constructor(@Inject(forwardRef(() => ServiceB)) private serviceB: ServiceB) {}\n}\n\n@Module({\n  imports: [forwardRef(() => ModuleB)],\n})\nexport class ModuleA {}\n",[26,1383,1384,1392,1403,1441,1445,1449,1459,1480,1486],{"__ignoreMap":162},[166,1385,1386,1388,1390],{"class":168,"line":169},[166,1387,260],{"class":176},[166,1389,838],{"class":263},[166,1391,390],{"class":180},[166,1393,1394,1396,1398,1401],{"class":168,"line":204},[166,1395,347],{"class":172},[166,1397,351],{"class":350},[166,1399,1400],{"class":354}," ServiceA",[166,1402,564],{"class":176},[166,1404,1405,1407,1410,1412,1414,1417,1419,1422,1424,1427,1429,1432,1434,1437,1439],{"class":168,"line":227},[166,1406,855],{"class":350},[166,1408,1409],{"class":176},"(@",[166,1411,922],{"class":263},[166,1413,267],{"class":180},[166,1415,1416],{"class":263},"forwardRef",[166,1418,267],{"class":180},[166,1420,1421],{"class":176},"()",[166,1423,1138],{"class":350},[166,1425,1426],{"class":180}," ServiceB)) ",[166,1428,860],{"class":350},[166,1430,1431],{"class":578}," serviceB",[166,1433,280],{"class":582},[166,1435,1436],{"class":354}," ServiceB",[166,1438,588],{"class":176},[166,1440,358],{"class":176},[166,1442,1443],{"class":168,"line":250},[166,1444,712],{"class":176},[166,1446,1447],{"class":168,"line":257},[166,1448,254],{"emptyLinePlaceholder":253},[166,1450,1451,1453,1455,1457],{"class":168,"line":273},[166,1452,260],{"class":176},[166,1454,264],{"class":263},[166,1456,267],{"class":180},[166,1458,270],{"class":176},[166,1460,1461,1463,1465,1467,1469,1471,1473,1475,1478],{"class":168,"line":293},[166,1462,277],{"class":276},[166,1464,280],{"class":176},[166,1466,686],{"class":180},[166,1468,1416],{"class":263},[166,1470,267],{"class":180},[166,1472,1421],{"class":176},[166,1474,1138],{"class":350},[166,1476,1477],{"class":180}," ModuleB)]",[166,1479,304],{"class":176},[166,1481,1482,1484],{"class":168,"line":307},[166,1483,338],{"class":176},[166,1485,341],{"class":180},[166,1487,1488,1490,1492,1495],{"class":168,"line":320},[166,1489,347],{"class":172},[166,1491,351],{"class":350},[166,1493,1494],{"class":354}," ModuleA",[166,1496,358],{"class":176},[23,1498,1499,1500,1502],{},"最佳实践：尽量避免循环依赖，若无法避免，使用 ",[26,1501,1416],{}," 并确保只在模块级别使用（不要过于深入）。",[47,1504,1506],{"id":1505},"三作用域scope","三、作用域（Scope）",[23,1508,1509],{},"提供者的生命周期由作用域决定。",[71,1511,1512,1524],{},[74,1513,1514],{},[77,1515,1516,1519,1521],{},[80,1517,1518],{},"作用域",[80,1520,88],{},[80,1522,1523],{},"生命周期",[90,1525,1526,1540,1553],{},[77,1527,1528,1534,1537],{},[95,1529,1530,1533],{},[31,1531,1532],{},"SINGLETON","（默认）",[95,1535,1536],{},"整个应用只有一个实例，所有请求共享",[95,1538,1539],{},"应用启动时创建，应用关闭时销毁",[77,1541,1542,1547,1550],{},[95,1543,1544],{},[31,1545,1546],{},"REQUEST",[95,1548,1549],{},"每个 HTTP 请求创建一个新实例（请求处理完后销毁）",[95,1551,1552],{},"针对每个请求单独创建",[77,1554,1555,1560,1563],{},[95,1556,1557],{},[31,1558,1559],{},"TRANSIENT",[95,1561,1562],{},"每次注入（每个消费者）创建一个全新实例",[95,1564,1565],{},"按需创建，不共享",[23,1567,368,1568,1571,1572,1575],{},[26,1569,1570],{},"@Injectable({ scope: Scope.REQUEST })"," 或 ",[26,1573,1574],{},"@Injectable({ scope: Scope.TRANSIENT })"," 指定。",[66,1577,1578],{"id":1578},"性能影响与适用场景",[818,1580,1581,1586,1591],{},[821,1582,1583,1585],{},[31,1584,1532],{},"：性能最好，无额外开销。适合大多数无状态服务（如数据库服务、工具类、仓储）。",[821,1587,1588,1590],{},[31,1589,1546],{},"：每个请求都会创建实例，会增加内存分配和 GC 压力。适合需要携带请求上下文的实例（如请求级缓存、用户会话数据）。",[821,1592,1593,1595],{},[31,1594,1559],{},"：每次注入创建新实例，开销最大。适合状态独立、不应共享的服务（如某个特定计算对象、临时数据处理器）。",[23,1597,1598,1601,1602,1605,1606,1609],{},[31,1599,1600],{},"注意","：REQUEST 和 TRANSIENT 作用域的提供者不能注入到 SINGLETON 提供者中（因为 SINGLETON 实例不会在请求结束后释放，会导致内存泄漏或状态混乱），除非通过 ",[26,1603,1604],{},"@Inject(forwardRef(...))"," 或使用 ",[26,1607,1608],{},"Request"," 作用域的代理模式（NestJS 内部有处理，但需谨慎）。通常，尽量保持默认 SINGLETON 作用域。",[47,1611,1612],{"id":1612},"总结",[71,1614,1615,1625],{},[74,1616,1617],{},[77,1618,1619,1622],{},[80,1620,1621],{},"模块特性",[80,1623,1624],{},"作用",[90,1626,1627,1639,1648,1656],{},[77,1628,1629,1636],{},[95,1630,1631,1633,1634],{},[26,1632,99],{}," \u002F ",[26,1635,144],{},[95,1637,1638],{},"模块间依赖共享",[77,1640,1641,1645],{},[95,1642,1643],{},[26,1644,365],{},[95,1646,1647],{},"全局模块，避免重复导入",[77,1649,1650,1653],{},[95,1651,1652],{},"重导出",[95,1654,1655],{},"聚合导出多个模块",[77,1657,1658,1661],{},[95,1659,1660],{},"动态模块",[95,1662,1663],{},"带配置参数的模块导入",[71,1665,1666,1675],{},[74,1667,1668],{},[77,1669,1670,1673],{},[80,1671,1672],{},"DI 特性",[80,1674,88],{},[90,1676,1677,1684,1699,1707],{},[77,1678,1679,1681],{},[95,1680,825],{},[95,1682,1683],{},"推荐注入方式，便于测试",[77,1685,1686,1689],{},[95,1687,1688],{},"自定义提供者",[95,1690,1691,40,1693,40,1695,40,1697],{},[26,1692,999],{},[26,1694,984],{},[26,1696,1014],{},[26,1698,1029],{},[77,1700,1701,1704],{},[95,1702,1703],{},"异步提供者",[95,1705,1706],{},"工厂可返回 Promise，依赖会等待",[77,1708,1709,1713],{},[95,1710,1711],{},[26,1712,1416],{},[95,1714,1715],{},"解决循环依赖",[71,1717,1718,1726],{},[74,1719,1720],{},[77,1721,1722,1724],{},[80,1723,1518],{},[80,1725,452],{},[90,1727,1728,1736,1743],{},[77,1729,1730,1733],{},[95,1731,1732],{},"SINGLETON（默认）",[95,1734,1735],{},"无状态服务",[77,1737,1738,1740],{},[95,1739,1546],{},[95,1741,1742],{},"需要请求级状态",[77,1744,1745,1747],{},[95,1746,1559],{},[95,1748,1749],{},"每次需全新实例",[23,1751,1752],{},"掌握这些概念，可以设计出清晰、可测试、高性能的 NestJS 应用。",[1754,1755,1756],"h2",{"id":1756},"参考文献",[23,1758,1759],{},"以下链接在编写时均可正常访问：",[71,1761,1762,1772],{},[74,1763,1764],{},[77,1765,1766,1769],{},[80,1767,1768],{},"资料",[80,1770,1771],{},"说明",[90,1773,1774,1787,1799],{},[77,1775,1776,1784],{},[95,1777,1778],{},[36,1779,1783],{"href":1780,"rel":1781},"https:\u002F\u002Fdocs.nestjs.com\u002F",[1782],"nofollow","NestJS 文档",[95,1785,1786],{},"官方",[77,1788,1789,1796],{},[95,1790,1791],{},[36,1792,1795],{"href":1793,"rel":1794},"https:\u002F\u002Fdocs.nestjs.com\u002Fmodules",[1782],"Modules",[95,1797,1798],{},"本章主题",[77,1800,1801,1808],{},[95,1802,1803],{},[36,1804,1807],{"href":1805,"rel":1806},"https:\u002F\u002Fdocs.nestjs.com\u002Ffaq\u002Frequest-lifecycle",[1782],"Request lifecycle",[95,1809,1810],{},"执行顺序",[1812,1813,1814],"style",{},"html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sucvu, html code.shiki .sucvu{--shiki-light:#E53935;--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":162,"searchDepth":204,"depth":204,"links":1816},[1817,1819,1820,1821,1822],{"id":49,"depth":227,"text":1818},"一、模块（@Module）",{"id":808,"depth":227,"text":809},{"id":1505,"depth":227,"text":1506},{"id":1612,"depth":227,"text":1612},{"id":1756,"depth":204,"text":1756},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Fmodule","knowledge\u002Fknowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Fmodule.md","md",{"items":1828},[1829,1833,1837,1841,1845,1849],{"path":1830,"title":1831,"description":1832,"category":10,"score":273},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fauth","认证与授权","认证（Authentication）：确认「你是谁」（如 JWT、Session）。 - 授权（Authorization）：确认「你能做什么」（如 RBAC、策略检查）。",{"path":1834,"title":1835,"description":1836,"category":10,"score":273},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcache","缓存","@nestjs\u002Fcache-manager 统一缓存 API，存储实现可插拔。",{"path":1838,"title":1839,"description":1840,"category":10,"score":273},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fservice","提供者与服务","Service 是最常见的 Provider，封装业务逻辑。见 module。",{"path":1842,"title":1843,"description":1844,"category":10,"score":273},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fguards","守卫 (Guards) 与授权","守卫决定是否放行请求，常用于认证与授权。见 auth。",{"path":1846,"title":1847,"description":1848,"category":10,"score":273},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fconfig","配置管理（Config 模块）","@nestjs\u002Fconfig 加载 .env 并提供 ConfigService。见 工程化 env。",{"path":1850,"title":1851,"description":1852,"category":10,"score":273},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdatabase","数据库集成（以 TypeORM 为例）","Nest 通过 @nestjs\u002Ftypeorm 等包集成 ORM；生产环境用 migration，慎用 synchronize。亦可选用 Prisma、MikroORM 等（见 官方 Database）。",{"series":1854,"title":1855,"items":1856,"index":703,"prev":1916,"next":1917},"booklet\u002Fend\u002Fnestjs\u002Fnew","new",[1857,1859,1862,1864,1866,1870,1874,1878,1880,1884,1888,1890,1894,1898,1902,1903,1906,1910,1912],{"path":1830,"title":1831,"date":1858,"pinned":15},"2025-12-23",{"path":43,"title":1860,"date":1861,"pinned":15},"NestJS 基础","2021-03-09",{"path":1834,"title":1835,"date":1863,"pinned":15},"2025-07-04",{"path":1846,"title":1847,"date":1865,"pinned":15},"2023-08-26",{"path":1867,"title":1868,"date":1869,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcontroller","控制器与路由","2020-07-18",{"path":1871,"title":1872,"date":1873,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcron","定时任务","2023-04-12",{"path":1875,"title":1876,"date":1877,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcustom-decorators","自定义装饰器","2021-09-19",{"path":1850,"title":1851,"date":1879,"pinned":15},"2023-05-26",{"path":1881,"title":1882,"date":1883,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdeploy","部署与运维","2023-01-24",{"path":1885,"title":1886,"date":1887,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Ferror","异常处理","2020-01-28",{"path":1842,"title":1843,"date":1889,"pinned":15},"2023-09-09",{"path":1891,"title":1892,"date":1893,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fintercept","拦截器 (Interceptors)","2021-04-26",{"path":1895,"title":1896,"date":1897,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Flogger","日志记录","2022-10-10",{"path":1899,"title":1900,"date":1901,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmiddleware","中间件 (Middleware)","2021-11-26",{"path":7,"title":8,"date":14,"pinned":15},{"path":1904,"title":1905,"date":1869,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fpipes","管道 (Pipes) 与数据验证",{"path":1907,"title":1908,"date":1909,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fqueue","队列（Bull）","2021-07-01",{"path":1838,"title":1839,"date":1911,"pinned":15},"2024-12-02",{"path":1913,"title":1914,"date":1915,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fwebsocket","WebSocket（网关）","2022-12-14",{"path":1899,"title":1900,"date":1901,"pinned":15},{"path":1904,"title":1905,"date":1869,"pinned":15}]