前面讲了 IOC、AOP、全局模块、动态模块、自定义 provider、生命周期等概念,比较零散,这节我们画图来整体串一串。
# 定义 provider
首先,provider 是可以注入的对象,它们都有 token,比如 @Injectable 装饰器声明的 class
token 可以是 class 也可以是 string:
provider 可以是 useClass 指定 class,也可以 useValue 指定值,或者 useFactory 动态创建。
provider 之间可以相互注入,还可以注入到 controller 里。
# 在 module 中引入
provider、controller 放在一个个 Module 里:
module 里 exports 的 provider 在模块被 imports 之后就可以用于别的模块的注入了。
或者可以通过 @Global 把这个模块声明为全局的,那样 Module 内的 provider 就可以在各处注入了。
Provider 可以通过 useFactory 动态创建,Module 也是,可以通过 register、forRoot、forFeature 等方法来动态创建。
# NestFactory.create 并执行生命周期
在 main.ts 里调用 NestFactory.create 方法,就会从 AppModule 开始递归解析 Module,实例化其中的 provider、controller,并依次调用它们的 onModuleInit 生命周期方法。
之后会再递归调用每个 Module 的 provider、controller 的还有 Module 自身的 onApplicationBootstrap 生命周期方法。
这样 Nest 就能对外提供服务了。
# Nest 从接收到请求,到返回响应的这个流程及各个切面
再就是 Nest 从接收到请求,到返回响应的这个流程,有很多切面。
路由最终是在 cotnroller 的方法,也就是 handler 里处理的。
在这个过程中,会经历很多层切面:
# 1.middleware
首先,请求会被 middleware 处理,这一层可以复用 express 的中间件生态,实现 session、static files 等功能。
这个 middleware 也可以是 Nest 的那种 class 的 middleware,可以注入 provider。
# 2.Guard
然后在具体的路由会经历 Guard 的处理,它可以通过 ExecutionContext 拿到目标 class、handler 的metadata 等信息,可以实现权限验证等功能。
# 3.Interceptor
之后是 Interceptor 可以在请求前后做一些处理,它也可以通过 ExecutionContext 拿到 class、handler 的信息。
# 4.Pipe
在到达 handler 之前,还会对参数用 Pipe 做下检验和转换。
# 5.Exception Filter
这个过程中不管是哪一层抛的异常,都会被 Exception Filter 处理下,返回给用户友好的响应信息。
这就是整个请求到响应的流程。
通过 AOP 的切面,可以把通用逻辑封装起来,在各处复用。
之后,Nest 销毁的时候,也会依次调用 Module 的 provider、controller 还有 Module 自己的 onModuleDestroy 方法、beforeApplicationShutdown 还有 onApplicationShutdown 的生命周期方法。
后两者的区别是 beforeApplication 可以拿到终止信号。
这就是 Nest 从创建、启动,到处理请求返回响应,再就是销毁的整个流程。
通过 IOC 实现了对象的自动创建、依赖的自动组装。
通过 AOP 实现了通用逻辑的抽取和复用。
IOC 内部的 Module 和 Provider 也都支持动态创建,灵活度很高。
# 总结
我们通过图解串了一下 Module、Provider、Controller、动态模块、全局模块、自定义 Provider、生命周期、Middleware、Guard、Pipe、Interceptor、Exception Filter 等概念。
对 IOC、AOP 也有了更加清晰的认识。
把这些核心概念理解了,对 Nest 就算有比较好的掌握了。