Nest 全局模块和生命周期

避免重复 imports。支持在创建和销毁时执行一些逻辑。

Posted by chanweiyan on April 26, 2026

全局模块

module 导出 provider,另一个 module 需要 imports 它才能用这些 provider。

如果这个模块被很多模块依赖,那每次都要 imports 就很麻烦。

能不能设置成全局的,它导出的 provider 直接可用呢?

1.常用引入模块方式

在 AaaModule 里指定 exports 的 provider

exports

然后,在 BbbModule 里 imports

imports

这样就可以在 BbbService 内注入 AaaService

注入 AaaService

2.@Global() 将模块声明为全局的

在 AaaModule 上加一个 @Global 的装饰器,然后,在 BbbModule 里把 AaaModule 的 imports 去掉。

在 BbbModule 里把 AaaModule 的 imports 去掉

依然可以注入AaaService

依然可以注入 AaaService

全局模块要尽量少用,不然,注入的很多 provider 都不知道来源,会降低代码的可维护性

生命周期

Module, Controller, Provider 是由 nest 创建的,能不能在创建,销毁时执行一些逻辑呢?

nest 在启动的时候,会递归解析 Module 依赖,扫描其中的 provider,controller,注入它的依赖。 全部解析完后,会监听网络端口,开始处理请求。 这个过程中,nest 暴漏了一些生命周期方法

lifecycle

1.创建阶段

nest 提供了两个 interface

1
2
3
4
5
6
7
8
export interface OnModuleInit {
  onModuleInit(): any;
}

export interface OnApplicationBootstrap {
  onApplicationBootstrap(): any;
}

在 controller,service,module 中分别实现它们:

controller,service,module

service

module

然后,重新运行服务,会看到下面的日志信息,显示了生命周期方法的调用顺序

日志信息

2.销毁阶段

1.先调用 每个模块的 contoller,provider 的 onModuleDestroy 方法, 然后,调用 Module 的 onModuleDestroy。

2.之后,再调用每个模块的 controller,provider 的 beforeApplicationShutdown 方法, 然后,调用 Module 的 beforeApplicationShutdown 方法。

3.然后,停止监听网络端口。

4.之后,调用每个模块 controller,provider 的 onApplicationShutdown 方法, 然后,调用 Module 的 onApplicationShutdown 方法。

5.之后停止进程。

onModuleDestroy 和 beforeApplicationShutdown 的区别

1
2
3
4
5
6
7
8
9
export interface OnModuleDestroy {
  onModuleDestroy(): any;
}

export interface BeforeApplicationShutdown {
  beforeApplicationShutdown(signal?: string): any; // 可以拿到 signal 系统信号,比如:SIGTERM
}

这些终止信号是别的进程传过来的,让它做一些销毁的事情,比如k8s管理容器的时候,可以通过这个信号来通知它。

controller

service

module

3秒后,调用 app.close() (只是触发销毁逻辑,不会真正退出进程)

只是触发销毁逻辑,不会真正退出进程)

生命周期方法执行顺序 生命周期方法执行顺序

所有的生命周期方法都支持 async

生命周期用法举例:

@nestjs/typeorm

@nestjs/mongoose

一般都通过 moduleRef 取出一些 provider 来销毁,比如关闭连接。