Nest.js如何无需构造传参在普通类中获取@Injectable单例引用
解决方案
在Nest.js中可以通过以下两种常用方案实现需求,无需在new时手动传入ConfigService实例:
方案1:静态属性挂载实例
在模块初始化阶段直接将容器管理的ConfigService单例,赋值给ConcreteClass的静态属性,所有实例可直接复用该属性:
- 调整ConcreteClass定义,新增静态属性存储ConfigService实例:
import { ConfigService } from './config.service'; export class ConcreteClass { // 静态属性存储全局唯一的ConfigService实例 static configService: ConfigService; getUrl(): string { return ConcreteClass.configService.someFunction(); } }
- 在ConfigService所属模块的生命周期钩子中完成实例赋值:
import { Module, OnModuleInit, Inject } from '@nestjs/common'; import { ConfigService } from './config.service'; import { ConcreteClass } from './concrete.class'; @Module({ providers: [ConfigService], exports: [ConfigService] }) export class ConfigModule implements OnModuleInit { constructor(@Inject(ConfigService) private configService: ConfigService) {} // 模块初始化完成后自动执行,完成实例挂载 onModuleInit() { ConcreteClass.configService = this.configService; } }
该方案实现简单,适合仅少数普通类需要访问注入实例的场景。
方案2:全局ModuleRef实例获取
将Nest的ModuleRef(依赖注入容器引用)全局暴露,普通类内部主动从容器中拉取ConfigService单例,无需逐个绑定静态属性:
- 项目入口文件中暴露全局ModuleRef:
// main.ts import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { ModuleRef } from '@nestjs/core'; let globalModuleRef: ModuleRef; // 对外暴露获取全局容器的方法 export function getGlobalModuleRef() { return globalModuleRef; } async function bootstrap() { const app = await NestFactory.create(AppModule); // 应用初始化完成后存储全局容器引用 globalModuleRef = app.get(ModuleRef); await app.listen(3000); } bootstrap();
- 在ConcreteClass中直接从全局容器获取实例:
import { getGlobalModuleRef } from './main'; import { ConfigService } from './config.service'; export class ConcreteClass { private configService: ConfigService; constructor() { // 从全局容器中获取ConfigService单例 this.configService = getGlobalModuleRef().get(ConfigService, { strict: false }); } getUrl(): string { return this.configService.someFunction(); } }
该方案适合有大量普通类需要访问注入实例的场景,复用性更强。
注意事项
- 所有
new ConcreteClass()的操作必须在Nest应用初始化完成后执行,否则实例还未挂载会抛出空指针错误 - 若ConfigService归属于特定业务模块,需保证对应模块已加载完成后再获取实例,避免查找失败
内容的提问来源于stack exchange,提问作者Maor Barazani
相关产品推荐
相关产品推荐

