NestJS继承类场景下基于属性的依赖注入失效如何解决
问题根因
- NestJS 的依赖注入仅会对被
@Injectable()装饰的类进行依赖处理,你当前的BaseService没有被@Injectable()修饰,也没有通过构造函数/属性装饰器声明依赖注入规则,因此utilsProvider无法被自动赋值,始终为 undefined。 - 你之前将 BaseService 封装为独立模块引入不生效的原因是:BaseService 作为抽象父类,实例化是由子类完成的,单独将其注册为 provider 不会处理继承场景下的依赖注入。
解决方案
方案1:构造函数透传依赖(官方推荐)
该方案依赖关系清晰,类型安全,适合绝大多数场景。
第一步:修改 BaseService 代码
import { Injectable, OnModuleInit } from '@nestjs/common'; import { Model } from 'mongoose'; import { UtilsProvider } from 'src/utils/utils.service'; import { DocumentType } from '@typegoose/typegoose'; // 注意导入缺失的类型 @Injectable() export class BaseService<MongooseModelT extends Record<string | number, any>> implements OnModuleInit { constructor( private mongooseModel: Model<DocumentType<MongooseModelT>>, // 将UtilsProvider加入构造参数 private utilsProvider: UtilsProvider ) {} async transform(){ // 可直接正常使用this.utilsProvider } }
第二步:修改子类代码,透传注入的依赖
import { Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; import { BaseService } from 'xxx/base.service'; // 替换为实际路径 import { CompanyDocument } from './schemas/company.schema'; import { CreateCompanyDto } from './dto/create-company.dto'; import { UtilsProvider } from 'src/utils/utils.service'; @Injectable() export class CompaniesService extends BaseService<CompanyDocument> { constructor( @InjectModel(Company.name) private companyModel: Model<CompanyDocument>, // 注入全局的UtilsProvider utilsProvider: UtilsProvider ) { // 透传给父类构造函数 super(companyModel, utilsProvider); } create(createCompanyDto: CreateCompanyDto) { return this.companyModel.create(createCompanyDto); } }
方案2:父类属性注入(适合父类依赖较多的场景)
该方案无需修改子类代码,通过属性装饰器自动完成注入。
仅需修改BaseService代码,添加@Inject装饰器即可
import { Inject, OnModuleInit } from '@nestjs/common'; import { Model } from 'mongoose'; import { UtilsProvider } from 'src/utils/utils.service'; import { DocumentType } from '@typegoose/typegoose'; export class BaseService<MongooseModelT extends Record<string | number, any>> implements OnModuleInit { // 声明该属性需要Nest注入UtilsProvider @Inject(UtilsProvider) private utilsProvider: UtilsProvider; constructor(private mongooseModel: Model<DocumentType<MongooseModelT>>) {} async transform(){ // 可直接正常使用this.utilsProvider } }
注意事项
- 请确保你已经在根模块
AppModule的imports数组中加入了UtilsModule,全局模块也需要在根模块导入一次才能全局生效。 - 如果你的
UtilsModule没有加@Global()装饰器,需要在所有继承BaseService的子类所属模块的imports数组中导入UtilsModule。
内容的提问来源于stack exchange,提问作者Tolga Oguz
相关产品推荐
相关产品推荐

