nest的核心概念

news2024/11/13 18:44:18

 请求进来 --- 中间件 --- 守卫 --- 拦截器 --- 通道 --- 处理(controller层) --- 拦截器 --- 返回

Pipe :  就是实现 PipeTransform 接口的 transform 方法,它的返回值就是传给 handler 的值。

-------------------------------------------

Nest框架内部是如何做到把TypeScript的类型定义变成功能实现?

Nest框架是一个基于Node.js的框架,它使用了TypeScript来提供强类型支持,并将类型定义与代码编译紧密结合。

TypeScript是一种静态类型检查的编程语言,它通过类型注解来在编译阶段检查代码的正确性。在Nest框架中,类型定义不仅仅是用来作为类型约束,还可以通过装饰器等方式对代码进行元编程,从而实现一些功能。

Nest框架使用了装饰器来定义控制器、提供者、中间件等组件,这些装饰器使用了TypeScript的类型系统来进行静态类型检查。在编译过程中,这些装饰器会被解析,并根据类型定义生成对应的代码。这意味着类型定义可以影响最终编译后的代码。

掘金小册  

 具体实现原理可以看这个章节。 

-------------------------

下面简单对章节进行总结: 

不知道大家有没有感觉很神奇,只是通过装饰器声明了一下,然后启动 Nest 应用,这时候对象就给创建好了,依赖也给注入了。

那它是怎么实现的呢?

Nest 的实现原理就是通过装饰器给 class 或者对象添加元数据,然后初始化的时候取出这些元数据,进行依赖的分析,然后创建对应的实例对象就可以了。

所以说,nest 实现的核心就是 Reflect metadata 的 api。

关于TypeScript部分,为什么跟Nest框架结合可以实现代码的功能改变,既元编程

其实还有一个疑问,依赖的扫描可以通过 metadata 数据,但是创建的对象需要知道构造器的参数,现在并没有添加这部分 metadata 数据呀:

这就不得不提到 TypeScript 的优势了,TypeScript 支持编译时自动添加一些 metadata 数据:

import "reflect-metadata";
 
class Guang {
  @Reflect.metadata("名字", "光光")
  public say(a: number): string {
    return '加油鸭';
  }
}

按理说我们只添加了一个元数据,生成的代码也确实是这样的:

但是呢,ts 有一个编译选项叫做 emitDecoratorMetadata,开启它就会自动添加一些元数据。

开启之后再试一下:

所以说,只要开启了这个编译选项,ts 生成的代码会自动添加一些元数据。

然后创建对象的时候就可以通过 design:paramtypes 来拿到构造器参数的类型了,那不就知道怎么注入依赖了么?

所以,nest 源码里你会看到这样的代码:

这也是为什么 nest 会用 ts 来写,因为它很依赖这个 emitDecoratorMetadata 的编译选项。

你用 cli 生成的代码模版里也都默认开启了这个编译选项:

-----

这就是 nest 的核心实现原理:通过装饰器给 class 或者对象添加 metadata,并且开启 ts 的 emitDecoratorMetadata 来自动添加类型相关的 metadata,然后运行的时候通过这些元数据来实现依赖的扫描,对象的创建等等功能。

Nest 的装饰器都是依赖 reflect-metadata 实现的,而且还提供了一个 @SetMetadata 的装饰器让我们可以给 class、method 添加一些 metadata

---

Nest 的装饰器的实现原理就是 Reflect.getMetadata、Reflect.defineMetadata 这些 api。通过在 class、method 上添加 metadata,然后扫描到它的时候取出 metadata 来做相应的处理来完成各种功能。

Nest 的 Controller、Module、Service 等等所有的装饰器都是通过 Reflect.meatdata 给类或对象添加元数据的,然后初始化的时候取出来做依赖的扫描,实例化后放到 IOC 容器里。

实例化对象还需要构造器参数的类型,这个开启 ts 的 emitDecoratorMetadata 的编译选项之后, ts 就会自动添加一些元数据,也就是 design:type、design:paramtypes、design:returntype 这三个,分别代表被装饰的目标的类型、参数的类型、返回值的类型。

当然,reflect metadata 的 api 还在草案阶段,需要引入 reflect metadata 的包做 polyfill。

Nest 还提供了 @SetMetadata 的装饰器,可以在 controller 的 class 和 method 上添加 metadata,然后在 interceptor 和 guard 里通过 reflector 的 api 取出来。

理解了 metadata,nest 的实现原理就很容易搞懂了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/811920.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python数据分析】Python常用内置函数(二)

🎉欢迎来到Python专栏~Python常用内置函数(二) ☆* o(≧▽≦)o *☆嗨~我是小夏与酒🍹 ✨博客主页:小夏与酒的博客 🎈该系列文章专栏:Python学习专栏 文章作者技术和水平有限,如果文…

Go语言进阶 + 依赖管理

依赖配置 - version开始,就开始很难听懂了,需要结合很多课后配套资料查阅很多文档和网站....然而好像没有那么多时间,一天给3小时学Go真的顶天了.....还有算法和Linux的Mysql... 这几天学Go已经把算法给挤掉了.....下步要权衡一下&#xff0c…

C#实现数据库数据变化监测(sqlservermysql)

监测数据库表数据变化,可实现数据库同步(一主一从(双机备份),一主多从(总部数据库,工厂1,工厂2,工厂数据合并到总部数据)) sqlserver 启用数据库…

【Linux】网络基础

🍎作者:阿润菜菜 📖专栏:Linux系统网络编程 文章目录 一、协议初识和网络协议分层(TCP/IP四层模型)认识协议TCP/IP五层(或四层)模型 二、认识MAC地址和IP地址认识MAC地址认识IP地址认…

什么是ssm?如何使用ssm进行后端开发

目录 一、ssm概述1.1 定义1.2 持久层框架 (mybatis&&mybatisPlus)1.3 Web 层框架 springMVC1.4 spring框架 二、开发结构2.1 config介绍2.2 controller介绍2.3 dao介绍2.4 domain介绍2.5 exception介绍2.6 interceptor介绍2.7 service介绍 三、注解开发介绍3.1 常见的注…

从零开始学Flask: 3分钟用Python快速构建Web应用

文章目录 一、背景二、安装&基础使用1. 安装 Flask2. 创建 Flask 应用3. 路由解析4. 模板渲染5. 请求和响应处理 三、Demo项目实战 一、背景 什么是Flask?Flask 是一个轻量级的 Python Web 应用框架,因其简单易用、灵活性高等特点,可以帮…

Ribbon源码

学了feign源码之后感觉,这部分还是按运行流程分块学合适。核心组件什么的,当专业术语学妥了。序章:认识真正のRibbon 但只用认识一点点 之前我们学习Ribbon的简单使用时,都是集成了Eureka-client或者Feign等组件,甚至在…

better scoll右 联左

这是先拿一个数组装进我们所有 获取到的dom节点的 高度 因为算的 都是 到最上面的 高度,所以我们 要减去他的 高度 就得到自身的高度 然后给右边加一个滚动事件,得到每一次滑动的高度,在循环上面的数组,就是我们右边的 y就在算出…

如何排查 IDEA 自身报错?| 以 IntelliJ IDEA 2023.1.4 无法刷新项目 Maven 模块的问题为例

这个问题是 2023 年 7 月 26 日遇到的,当时还是 IDEA 2023.1.4,结果文章还没写完,7 月 27 日自动给更新了 IDEA 2023.2。问题估计解决了。 所以,本文就简单提一下 IDEA 自身报错的排查方法。 规避/解决方式 先说问题怎么处理&am…

重生之我要学C++第五天

这篇文章主要内容是构造函数的初始化列表以及运算符重载在顺序表中的简单应用,运算符重载实现自定义类型的流插入流提取。希望对大家有所帮助,点赞收藏评论,支持一下吧! 目录 构造函数进阶理解 1.内置类型成员在参数列表中的定义 …

糟了,数据库主从延迟了!

前言 在实际的生产环境中,由单台MySQL作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面 因此,一般来说都是通过集群主从复制(Master-Slave)的方式来同步数据&…

【点云处理教程】05-Python 中的点云分割

一、说明 这是我的“点云处理”教程的第 5 篇文章。“点云处理”教程对初学者友好,我们将在其中简单地介绍从数据准备到数据分割和分类的点云处理管道。 在上一教程中,我们看到了如何过滤点云以减少噪声或其密度。在本教程中,我们将应用一些聚…

LeetCode_11. 盛最多水的容器

题目描述 11. 盛最多水的容器 - 力扣(LeetCode)https://leetcode.cn/problems/container-with-most-water/ 思路分析 这题就是典型的是一道很经典的面试题,最优的解法是双指针,但很多人在第一次看到这题的时候很难想到用双指针来…

*CTF 2023 Misc

一、 snippingTools Alice在参加某个CTF比赛,她成功的解出了一道题,拿到了flag。她很开心,迫不及待地想要向Bob分享她的喜悦。于是按下了快捷键ShiftWinS使用了Windows 11的截图工具,截取了整个屏幕,并且保存为文件1.p…

无涯教程-jQuery - Spinner组件函数

Widget Spinner 函数可与JqueryUI中的窗口小部件一起使用。Spinner提供了一种从一组中选择一个值的快速方法。 Spinner - 语法 $( "#menu" ).selectmenu(); Spinner - 示例 以下是显示Spinner用法的简单示例- <!doctype html> <html lang"en"…

(树) 剑指 Offer 27. 二叉树的镜像 ——【Leetcode每日一题】

❓剑指 Offer 27. 二叉树的镜像 难度&#xff1a;简单 请完成一个函数&#xff0c;输入一个二叉树&#xff0c;该函数输出它的镜像。 例如输入&#xff1a; 4/ \2 7/ \ / \1 3 6 9镜像输出&#xff1a; 4/ \7 2/ \ / \9 6 3 1示例 1&#xff1a; 输…

给你一个项目,你将如何开展性能测试工作?

一、性能三连问 1、何时进行性能测试&#xff1f; 性能测试的工作是基于系统功能已经完备或者已经趋于完备之上的&#xff0c;在功能还不够完备的情况下没有多大的意义。因为后期功能完善上会对系统的性能有影响&#xff0c;过早进入性能测试会出现测试结果不准确、浪费测试资…

We are the Lights - 思维

分析&#xff1a; 每次操作会把上一次的状态覆盖&#xff0c;但是从后往前操作可以保留最后一次覆盖&#xff0c;每一个位置最后的覆盖状态一定是最终状态&#xff0c;因此可以存下来从后往前记录第一次覆盖的状态并计数。 代码&#xff1a; #include <bits/stdc.h>usi…

玩转LaTeX(一)【源文件基本结构、中文处理方法、中英文的字体字号设置、文档基本结构】

latex源文件基本结构&#xff1a; 【在latex中一般分为两个区&#xff0c;一个是导言区&#xff0c;一个是正文区&#xff08;文稿区&#xff09;】 %导言区(主要进行全局设置)%一个latex文件&#xff0c;只能有且只有一个document环境\documentclass{article} %除article类外…

OpenHarmony开源鸿蒙学习入门 - 基于3.2Release 应用开发环境安装

OpenHarmony开源鸿蒙学习入门 - 基于3.2Release 应用开发环境安装 基于目前官方master主支&#xff0c;最新文档版本3.2Release&#xff0c;更新应用开发环境安装文档。 一、安装IDE&#xff1a; 1.IDE安装的系统要求 2.IDE下载官网链接&#xff08;IDE下载链接&#xff09; …