3 Nestjs的模块(@Module)Nestjs实现了控制反转 , 约定配置模块(@module)的 imports、exports、providers 管理提供者也就是类的依赖注入 。
providers 可以理解是在当前模块注册和实例化类 , 下面的 A 和 B 就在当前模块被实例化 , 如果B在构造函数中引用 A , 就是引用的当前 ModuleD 的 A 实例 。
import { Module } from '@nestjs/common';import { ModuleX } from './moduleX';import { A } from './A';import { B } from './B';@Module({ imports: [ModuleX], providers: [A,B], exports: [A]})export class ModuleD {}// Bclass B{ constructor(a:A){ this.a = a; }}exports
就是把当前模块中的 providers
中实例化的类 , 作为可被外部模块共享的类 。 比如现在 ModuleF 的 C 类实例化的时候 , 想直接注入 ModuleD 的 A 类实例 。 就在 ModuleD 中设置导出(exports)A , 在 ModuleF 中通过 imports
导入 ModuleD 。
按照下面的写法 , 控制反转程序会自动扫描依赖 , 首先看自己模块的 providers 中 , 有没有提供者 A , 如果没有就去寻找导入的 ModuleD 中是否有 A 实例 , 发现存在 , 就取得 ModuleD 的 A 实例注入到 C 实例之中 。
import { Module } from '@nestjs/common';import { ModuleD} from './moduleD';import { C } from './C';@Module({ imports: [ModuleD], providers: [C],})export class ModuleF {}// Cclass C { constructor(a:A){ this.a = a; }}因此想要让外部模块使用当前模块的类实例 , 必须先在当前模块的providers
里定义实例化类 , 再定义导出这个类 , 否则就会报错 。
//正确@Module({ providers: [A], exports: [A]})//错误@Module({ providers: [], exports: [A]})
后期补充模块查找实例的过程回看了一下 , 确实有点不清晰 。 核心点就是providers里的类会被实例化 , 实例化后就是提供者 , 模块里只有providers里的类会被实例化 , 而导出和导入只是一个组织关系配置 。 模块会优先使用自己的提供者 , 如果没有 , 再去找导入的模块是否有对应提供者这里还是提一嘴ts的知识点
export class C { constructor(private a: A) { }}由于 TypeScript 支持 constructor 参数(private、protected、public、readonly)隐式自动定义为 class 属性 (Parameter Property) , 因此无需使用
this.a = a
。 Nest 中都是这样的写法 。 4 Nest 元编程元编程的概念在 Nest 框架中得到了体现 , 它其中的控制反转、装饰器 , 就是元编程的实现 。 大概可以理解为 , 元编程本质还是编程 , 只是中间多了一些抽象的程序 , 这个抽象程序能够识别元数据(如@Module中的对象数据) , 其实就是一种扩展能力 , 能够将其他程序作为数据来处理 。 我们在编写这样的抽象程序 , 就是在元编程了 。
4.1 元数据
Nest 文档中也常提到了元数据 , 元数据这个概念第一次看到的话 , 也会比较费解 , 需要随着接触时间增长习惯成理解 , 可以不用太过纠结 。
元数据的定义是:描述数据的数据 , 主要是描述数据属性的信息 , 也可以理解为描述程序的数据 。
Nest 中 @Module 配置的
exports、providers、imports、controllers
都是元数据 , 因为它是用来描述程序关系的数据 , 这个数据信息不是展示给终端用户的实际数据 , 而是给框架程序读取识别的 。 4.2 Nest 装饰器
如果看看 Nest 中的装饰器源码 , 会发现 , 几乎每一个装饰器本身只是通过 reflect-metadata 定义了一个元数据 。
@Injectable装饰器
export function Injectable(options?: InjectableOptions): ClassDecorator { return (target: object) => { Reflect.defineMetadata(INJECTABLE_WATERMARK, true, target); Reflect.defineMetadata(SCOPE_OPTIONS_METADATA, options, target); };}这里存在反射的概念 , 反射也比较好理解 , 拿 @Module 装饰器举例 , 定义元数据
providers
, 只是往providers
数组里传入了类 , 在程序实际运行时providers
里的类 , 会被框架程序自动实例化变为提供者 , 不需要开发者显示的去执行实例化和依赖注入 。 类只有在模块中实例化了之后才变成了提供者 。 providers
中的类被反射了成了提供者 , 控制反转就是利用的反射技术 。 换个例子的话 , 就是数据库中的 ORM(对象关系映射) , 使用 ORM 只需要定义表字段 , ORM 库会自动把对象数据转换为 SQL 语句 。
const data = https://www.52zixue.com/zhanzhang/webqd/js/04/09/69299/TableModel.build();data.time = 1;data.browser = 'chrome'; data.save();// SQL: INSERT INTO tableName (time,browser) [{"time":1,"browser":"chrome"}]
推荐阅读
- 剑与远征8月26日兑换码分享-8月兑换码大全您需要了解的
- 帕斯卡契约星环之坠图鉴-星环之坠战利品介绍您需要了解的
- 养胃的一些禁忌你得了解 饥一顿饱一顿最易致胃病
- 小编详解win7正版多少钱新系统了解的东西
- 任务栏颜色,图文告诉您如何更改任务栏颜色新系统了解的东西
- Win7鼠标右键失效不能复制粘贴怎么办?小编教你新系统了解的东西
- 分享写优秀文案的5种方法 写优秀文案的方法有哪些?
- word打不开发送错误报告怎么办 word弹出错误报告解决方法新系统了解的东西
- Win7系统任务栏变宽变窄怎么还原?小编教你新系统了解的东西
- 网络不稳定是什么原因?小编教你Win7网络不稳定的解决方法新系统了解的东西