Module 概念
模块使用@Module()
装饰器来装饰的类。装饰器@Module()
提供 NestJS 用于组织应用程序结构相关的数据,例如提供商和控制器等等。具体的结构图如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T3CAmLIm-1690294965361)(./images/模块关系例子.png “模块关系例子”)]
每个应用程序至少有一个模块,即根模块
。
根模块是 NestJS 用于构建应用程序的起点,根模块也是用于解析模块和提供者关系依赖关系的内部数据结构图。
强烈建议将模块作为组织组件的有效方式。因此,对于大多数应用程序来说,最终的架构将采用多个模块,每个模块封装一组密切相关的功能。
@Module
装饰器是一个对象,其属性具体如下:
属性 | 属性说明 |
---|---|
providers | 将由 Nest 注入器实例化的提供程序(提供者的注入),并且至少可以在该模块中共享 |
controllers | 该模块中定义的必须实例化的控制器集 |
imports | 导入通用的业务模块,例如缓存模块、日志模块等 |
exports | 导出该模块所需的提供程序,只有导出的模块才能够被引用 |
功能模块
功能模块只是组织与特定功能相关的代码,保持代码组织并建立清晰的边界。Controller
和Service
在功能上是密切关联的,所以我们可以把他们多移入功能模块中进行管理。具体的实例如下:
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 {}
在功能模块中声明了Controller
和Service
后,就不必在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、全局模块虽然可以减少部分代码量,但是这不是推荐的行为。