NestJS 的 Module 学习

Module 概念

模块使用@Module()装饰器来装饰的类。装饰器@Module()提供 NestJS 用于组织应用程序结构相关的数据,例如提供商和控制器等等。具体的结构图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T3CAmLIm-1690294965361)(./images/模块关系例子.png “模块关系例子”)]

每个应用程序至少有一个模块,即根模块

根模块是 NestJS 用于构建应用程序的起点,根模块也是用于解析模块和提供者关系依赖关系的内部数据结构图。

强烈建议将模块作为组织组件的有效方式。因此,对于大多数应用程序来说,最终的架构将采用多个模块,每个模块封装一组密切相关的功能。

@Module装饰器是一个对象,其属性具体如下:

属性 属性说明
providers 将由 Nest 注入器实例化的提供程序(提供者的注入),并且至少可以在该模块中共享
controllers 该模块中定义的必须实例化的控制器集
imports 导入通用的业务模块,例如缓存模块、日志模块等
exports 导出该模块所需的提供程序,只有导出的模块才能够被引用

功能模块

功能模块只是组织与特定功能相关的代码,保持代码组织并建立清晰的边界。ControllerService在功能上是密切关联的,所以我们可以把他们多移入功能模块中进行管理。具体的实例如下:

import {
    
     Module } from "@nestjs/common";
import {
    
     CommodityController } from "../controller/commodity.controller";
import {
    
     CommodityService } from "../service/commodity.service";

@Module({
    
    
  controllers: [CommodityController],
  providers: [CommodityService],
})
export class CommodityModule {
    
    }

在功能模块中声明了ControllerService后,就不必在app.module中声明,只是我们要把功能模块声明到这里,具体实例如下:

@Module({
    
    
  imports: [CommodityModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {
    
    }

共享模块

在 NestJS 中,默认情况下模块是单例的,因此我们可以轻松地在多个模块之间共享任何一个实例。具体结构图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JHlQvqWY-1690294965363)(./images/共享模块.png “共享模块”)]

假设我们想要在几个模块之间共享CommodityService的实例,我们只需要使用exports属性就可以对外暴露实例,从而其他模块就可以使用。具体实例如下:

@Module({
    
    
  controllers: [CommodityController],
  providers: [CommodityService],
  exports: [CommodityService],
})
export class CommodityModule {
    
    }

现在,只要导入CommodityModule后就可以使用CommodityService的实例,并且这个 Service 实例都是共享同一个。具体的实例如下:

// module模块
@Module({
    
    
  imports: [CommodityModule], // app.module没有导入的话,这里是需要导入才可以实例化对应的提供者
  controllers: [AccountController],
  providers: [AccountService],
})
export class AccountModule {
    
    }

// 控制器模块
@Controller("account")
export class AccountController {
    
    
  constructor(
    private commodityService: CommodityService,
    private accountService: AccountService
  ) {
    
    }

  @Get("/info")
  getInfo(@Param() params: {
    
     id: string }) {
    
    
    const _commodity = this.commodityService.findById(params.id);
    return this.accountService.findById(_commodity?.id);
  }
}

模块重新导出(这里可能有理解上的错误,大佬们发现有错误的描述可以留言)

模块重新导出主要是暴露对应的所有方法。具体实例如下:

@Module({
    
    
  imports: [CommonModule],
  exports: [CommonModule],
})
export class CoreModule {
    
    }

上面这个例子主要是让CoreModule能够使用CommonModule里面所有注入的服务。

全局模块

当程序在各处需要导入相同的模块集时,我们可以使用全局装饰器@Global()来声明模块,这样模块就会变为全局可以访问的模块。具体实例如下:

import {
    
     Global, Module } from "@nestjs/common";
import {
    
     CommodityController } from "../controller/commodity.controller";
import {
    
     CommodityService } from "../service/commodity.service";

@Global()
@Module({
    
    
  controllers: [CommodityController],
  providers: [CommodityService],
  exports: [CommodityService],
})
export class CommodityModule {
    
    }

全局装饰器使得模块范围变成全局访问,全局模块只是注册一次就可以,通常是由根模块或者核心模块进行注册。

注意一下几点:

  • 1、当我们把模块升级为全局模块后,我们就可以不用在用imports进行导入模块啦。
  • 2、全局模块还是需要使用exports导出提供者才行,要不然其他模块是不能使用到实例的。
  • 3、全局模块虽然可以减少部分代码量,但是这不是推荐的行为。

猜你喜欢

转载自blog.csdn.net/qq_33003143/article/details/131927638