如何在Nest.js中动态注入不同的提供者?
解决NestJS中动态指定QueueService依赖提供者的问题
下面提供三种可行的实现方案,可根据业务场景选择:
方案一:创建独立的QueueService实例(推荐,符合NestJS依赖注入规范)
通过为不同的Pubsub提供者创建专属的QueueService实例,控制器直接注入对应实例使用。
步骤1:修改AppModule配置
在providers中添加两个QueueService的自定义提供者,分别绑定不同的Pubsub:
import { PubsubService } from '@myorg/queue' import { QueueService } from './queue.service'; @Module({ imports: [ ConfigModule.forRoot({ validationSchema: Joi.object({ SHARED_RESOURCES_PROJECT_ID: Joi.string().required() }) }) ], controllers: [AppController], providers: [ { provide: 'PUBSUB', useValue: new PubsubService() }, { provide: 'INTEGRATION_PUBSUB', useValue: new PubsubService({ projectId: process.env.SHARED_RESOURCES_PROJECT_ID }) }, // 绑定默认QueueService到PUBSUB { provide: 'DEFAULT_QUEUE_SERVICE', useClass: QueueService, inject: ['PUBSUB'] }, // 绑定集成用QueueService到INTEGRATION_PUBSUB { provide: 'INTEGRATION_QUEUE_SERVICE', useClass: QueueService, inject: ['INTEGRATION_PUBSUB'] } ] }) export class AppModule {}
步骤2:修改控制器注入两个QueueService实例
@Controller() export class AppController { constructor( @Inject('DEFAULT_QUEUE_SERVICE') private readonly defaultQueueService: QueueService, @Inject('INTEGRATION_QUEUE_SERVICE') private readonly integrationQueueService: QueueService ) {} @Post() async create() { // 使用绑定PUBSUB的QueueService return this.defaultQueueService.sendMessage(...) } @Patch() async update() { // 使用绑定INTEGRATION_PUBSUB的QueueService return this.integrationQueueService.sendMessage(...) } }
原QueueService无需修改,保持现有代码即可。
方案二:让QueueService支持动态切换Pubsub
在QueueService内部注入所有Pubsub实例,通过方法参数指定使用哪个提供者。
修改QueueService代码
@Injectable() export class QueueService { private pubsubMap: Record<string, PubsubService>; constructor( @Inject('PUBSUB') private readonly defaultPubsub: PubsubService, @Inject('INTEGRATION_PUBSUB') private readonly integrationPubsub: PubsubService ) { this.pubsubMap = { 'PUBSUB': defaultPubsub, 'INTEGRATION_PUBSUB': integrationPubsub }; } async sendMessage(payload, providerKey: string = 'PUBSUB'): Promise<void> { const pubsub = this.pubsubMap[providerKey]; if (!pubsub) { throw new Error(`Unknown Pubsub provider: ${providerKey}`); } return pubsub.sendMessage(payload); } }
控制器调用时指定提供者
@Controller() export class AppController { constructor(private readonly queueService: QueueService) {} @Post() async create() { return this.queueService.sendMessage(..., 'PUBSUB') } @Patch() async update() { return this.queueService.sendMessage(..., 'INTEGRATION_PUBSUB') } }
方案三:使用工厂模式动态创建QueueService
创建工厂类,根据传入的提供者key返回对应的QueueService实例。
步骤1:创建QueueService工厂
@Injectable() export class QueueServiceFactory { constructor( @Inject('PUBSUB') private readonly defaultPubsub: PubsubService, @Inject('INTEGRATION_PUBSUB') private readonly integrationPubsub: PubsubService ) {} createQueueService(providerKey: string): QueueService { let pubsub: PubsubService; switch(providerKey) { case 'PUBSUB': pubsub = this.defaultPubsub; break; case 'INTEGRATION_PUBSUB': pubsub = this.integrationPubsub; break; default: throw new Error(`Unknown Pubsub provider: ${providerKey}`); } return new QueueService(pubsub); } }
步骤2:模块中注册工厂
@Module({ // ... 其他配置 providers: [ // ... 原有PUBSUB、INTEGRATION_PUBSUB提供者 QueueServiceFactory ] }) export class AppModule {}
步骤3:控制器中使用工厂创建实例
@Controller() export class AppController { constructor(private readonly queueFactory: QueueServiceFactory) {} @Post() async create() { const queueService = this.queueFactory.createQueueService('PUBSUB'); return queueService.sendMessage(...) } @Patch() async update() { const queueService = this.queueFactory.createQueueService('INTEGRATION_PUBSUB'); return queueService.sendMessage(...) } }
内容的提问来源于stack exchange,提问作者pakut2
相关产品推荐
相关产品推荐

