NestJS如何匹配注入目标和注入的实例



根据NestJS官方文件[1],它描述了"在Nest中,得益于TypeScript功能,管理依赖关系非常容易,因为它们只通过类型进行解析">

我对这个描述很困惑,因为在运行时,我们没有构造函数参数的任何类型信息,这些信息在转换过程中被删除。

NestJS实际上是如何解决所需类型(类)和实际对象(实例)之间的匹配的?

多亏了decorator,我们实际上可以通过Typescript发出的元数据访问一些类型。Nest能够通过读取这些元数据来了解如何将类实例注入到提供程序中。这是从nest newapp.service.tsapp.service.js文件的编译JS

"use strict";
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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppService = void 0;
const common_1 = require("@nestjs/common");
let AppService = class AppService {
getHello() {
return 'Hello World!';
}
};
AppService = __decorate([
(0, common_1.Injectable)()
], AppService);
exports.AppService = AppService;
//# sourceMappingURL=app.service.js.map

这是app.controller.js

"use strict";
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);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppController = void 0;
const common_1 = require("@nestjs/common");
const app_service_1 = require("./app.service");
let AppController = class AppController {
constructor(appService) {
this.appService = appService;
}
getHello() {
return this.appService.getHello();
}
};
__decorate([
(0, common_1.Get)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", String)
], AppController.prototype, "getHello", null);
AppController = __decorate([
(0, common_1.Controller)(),
__metadata("design:paramtypes", [app_service_1.AppService])
], AppController);
exports.AppController = AppController;
//# sourceMappingURL=app.controller.js.map

如果我们看app.controller.js的最后几行,我们可以看到一行__metadata("design:paramtypes", [app_service_1.AppService])。这一行意味着AppController的构造函数具有类型为AppService的参数,这些参数应该传递给它。Nest能够读取这些参数,检查模块容器的提供程序中是否存在AppService,如果存在,则将提供程序中的实例映射到new AppController()。这个发出的类型数据可用于上面有装饰器的类,并且发出的类型值始终是一个类,无论它是使用的自定义类,还是像ObjectString这样的基元类,尽管在后一种情况下,应该有一个通过@Inject()装饰器发出的自定义参数元数据。

实际上,里面没有什么神奇的东西。随意查看https://github.com/nestjs/nest/blob/874344c60efddba0d8491f8bc6da0cd45f8ebdf7/packages/core/scanner.ts#L415

最新更新