NestJS:依赖项注入和提供者注册 [英] NestJS: Dependency Injection and Provider Registration

查看:36
本文介绍了NestJS:依赖项注入和提供者注册的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有人能帮我理解DI Nest的基本原理,我的问题是:

";是否可以有一个没有@Injectable Annottion的服务类,而且这个类不属于任何模块?";我在网上看到过如下示例:

此类存在于公用文件夹中:

export class NotificationService {
  constructor(
    @Inject(Logger) private readonly logger: LoggerService,
    private readonly appConfigService: AppConfigService,
    @Inject(HttpService) private readonly httpService: HttpService
  ) {}
 
  async sendNotification(msg: string) {
   ....
  } 
}

然后在提供程序数组的另一个模块中注册:

import { Module, Logger, forwardRef, HttpModule } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { NotificationService } from '../../commons/notification/notification.service';
 
@Module({
    imports: [
        ...
    ],
    controllers: [InvoiceController],
    providers: [
        InvoiceService,
        NotificationService,
        Logger],
    exports: [InvoiceService]
})
export class InvoiceModule { }

然后将其注入到其他服务的构造函数方法中

@Injectable()
export class InvoiceService {
 
    constructor(
        @Inject(Logger) private readonly logger: LoggerService,
        private readonly notificationService: NotificationService) { }
 
...
}

这个工作得很好,但我不知道为什么。为什么在不使用add@injectable和不使用and import模块的情况下正确注入通知服务?

推荐答案

所以让我们详细分析一下@Injectable()装饰符的实际情况。

通常,我们使用修饰符来设置关于我们正在修饰的类、参数、方法或属性的元数据,或者我们使用它通过描述符以某种方式修改方法(如果是方法修饰符)或属性(属性修饰符)。在@Injectable()的情况下,我们实际上不会执行这两种操作。当然我们是setting the scope metadata,但是这似乎并没有真正设置任何关于";的元数据。嘿,这个类是可以通过Nest框架";注入的。这是因为@Injectable()真正设置我们的是tsconfigtsc编译器的一个特殊属性,即emitDecoratorMetadata属性。有了这个属性,TypeScript将在文件的开头和结尾处添加一组额外的函数。这些函数通常如下所示

var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};

DelegatorService = __decorate([
    common_1.Injectable(),
    __metadata("design:paramtypes", [http_interceptor_service_1.HttpInterceptorService,
        websocket_interceptor_service_1.WebsocketInterceptorService,
        rpc_interceptor_service_1.RpcInterceptorService,
        gql_interceptor_service_1.GqlInterceptorService])
], DelegatorService);

这是非常重要的部分,因为这"design:paramtypes"实际上是Nest在确定要注入的内容时读取的内容。

此元数据仅在类中的任何位置使用装饰符时才可用,并且有关于元数据的was actually an eslint-typescript discussion以及import type如何破坏它的信息,以及真正进入杂草的a recent PR

我提出所有这些都是为了说明,因为构造函数中有@Inject(),所以@Injectable()实际上是无关的,除非您要设置作用域级别的元数据,否则不是必需的。类型元数据已经发出,所以这就解释了为什么您不需要@Injectable()(尽管我仍然认为让它提供明确的意图是个好主意)。

现在,关于注入正常工作的原因,我保证这个不会太复杂:您向InvoiceModule‘s providersarray. This tells Nest that any service inside ofInvoiceModulehas access toNotificationsService`添加了NotificationsService,这样它就可以毫无问题地注入到这里。

这篇关于NestJS:依赖项注入和提供者注册的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆