当前位置: 首页 > news >正文

【NestJS】深入理解NestJS装饰器原理

NestJS 的装饰器系统是整个框架的“灵魂之一”,理解它的原理、运行时机和执行顺序,就能真正搞懂控制器、依赖注入、管道、拦截器等机制的底层逻辑。

🌱 一、装饰器是什么?(TypeScript 层面)

装饰器其实就是一个能改造类或类成员的函数

NestJS 本质上只是利用了 TypeScript 提供的装饰器语法糖 + Reflect Metadata 机制。

简单来说:

  • TypeScript 在编译时遇到 @Something 时,会调用这个装饰器函数;
  • 装饰器函数可以拿到目标(类、方法、属性、参数);
  • NestJS 再利用这些信息,在启动时构建路由、依赖注入等逻辑。

🧩 二、装饰器的类型(Nest 常用的 4 种)

类型示例应用于常见用途
类装饰器@Controller()@Injectable()定义控制器、模块、服务等
方法装饰器@Get()@Post()类的方法定义路由和请求方法
参数装饰器@Body()@Param()方法参数提取请求参数
属性装饰器@Inject()@Autowired()类的属性实现依赖注入

🧠 三、装饰器的运行时机(非常关键)

NestJS 的装饰器 不是运行时调用的,而是在类定义阶段就执行!

也就是说:

@Controller('user')
export class UserController {@Get()getUser() {}
}

Nest 应用还没启动时,这两个装饰器已经执行了:

  1. TypeScript 在加载 UserController 类时;
  2. 它会调用 @Controller()
  3. 然后再调用 @Get()
  4. 最后把元数据存到 Reflect(反射)里。

Nest 启动时会遍历这些类 → 读取元数据 → 生成路由表。

👉 所以装饰器运行在“类加载阶段”,而不是请求到来时。


🔍 四、简单示例:自定义装饰器运行原理

import 'reflect-metadata';function MyController(prefix: string) {return (target: any) => {Reflect.defineMetadata('prefix', prefix, target);console.log(`[装饰器执行] 定义控制器:${prefix}`);};
}function MyGet(path: string) {return (target: any, key: string, descriptor: PropertyDescriptor) => {Reflect.defineMetadata('path', path, descriptor.value);console.log(`[装饰器执行] 定义路由:${path}`);};
}@MyController('user')
class UserController {@MyGet('list')getList() {}
}

运行结果(还没创建任何实例):

[装饰器执行] 定义路由:list
[装饰器执行] 定义控制器:user

✅ 装饰器在类被定义时立即执行,而不是在调用 new UserController() 或请求时。


⚙️ 五、多个装饰器的执行顺序

这是最容易搞混的地方。我们来分两种情况

① 同一目标多个装饰器

比如:

@A()
@B()
class Test {}

执行顺序:

  • 从下到上执行(B → A)

② 嵌套装饰器(函数调用嵌套)

比如:

@A(B())
class Test {}

执行顺序:

  • 从内到外执行函数调用(先调用 B() 再执行 A());
  • 装饰应用顺序仍然是从下到上。

🧪 举个 Nest 风格例子:

function Log(name: string) {return (target: any, key: string, descriptor: PropertyDescriptor) => {console.log(`运行 Log(${name})`);};
}function Auth(role: string) {return (target: any, key: string, descriptor: PropertyDescriptor) => {console.log(`运行 Auth(${role})`);};
}class UserController {@Log('list')@Auth('admin')getList() {}
}

输出结果:

运行 Auth(admin)
运行 Log(list)

顺序:从下往上执行
也就是 @Auth@Log 先执行。


🏗️ 六、NestJS 真实装饰器执行流程图

Controller 装饰器 (@Controller)│├──> 注册控制器元数据│└──> 遍历控制器方法│├──> 执行路由装饰器 (@Get, @Post...)│      ├──> 记录 HTTP 方法与路径│      └──> 绑定到控制器的 method 上│└──> 执行参数装饰器 (@Body, @Param...)├──> 记录参数类型与来源└──> 创建请求解析逻辑

最终 Nest 启动时会读取这些 Reflect Metadata,构建:

  • 路由映射表
  • 参数解析逻辑
  • 依赖注入容器
  • 生命周期绑定

🚀 七、总结一句话(记忆口诀)

“装饰器定义时执行,Reflect 记下元数据,Nest 启动时读取,最终请求时应用。”

阶段发生了什么
编译加载时装饰器执行,元数据写入 Reflect
Nest 启动时Nest 读取元数据,注册控制器和依赖
请求到来时使用元数据完成参数注入、验证、执行等逻辑

🎯 八、拓展:查看装饰器生成的元数据

你可以在 Nest 启动后打印:

const prefix = Reflect.getMetadata('path', UserController);
console.log(prefix);

或者调试时看:

console.log(Reflect.getMetadataKeys(UserController));

就能看到 Nest 的内部“路由表是怎么生成的”。


http://www.dtcms.com/a/529389.html

相关文章:

  • 网站设计师接单网站建设的大概费用
  • 俐侎族网站建设背景wordpress自动修改图
  • 西双版纳网站建设公司国内最大的域名交易平台
  • 湘潭市建设工程质量监督站网站微信推广朋友圈广告
  • 企业网站网址化工企业网站模板 aspx
  • 知识图谱构建流程与技术架构
  • 重庆手机网站制作wordpress 4.2.8
  • 16 Electron 应用自动更新方案:electron-updater 完整指南
  • 手机网站页面如何制作软件商贸有限公司企业简介
  • 重庆长寿网站设计公司哪家好做酒店管理网站的作用
  • 【系统分析师】高分论文:论需求分析及其应用(配网运维管控项目)
  • 大专计算机技术专业就业方向:解读、规划与提升指南
  • 如何在手机上做网站用dreamware制作网页
  • C# 可空类型
  • 数据结构12:二叉树的API及其实现
  • 用c 建网站时怎么做导航菜单栏访问升级每天自动更新
  • 江门做网站设计wordpress通用页面模板
  • 苏州吴中区专业做网站网站建设制作设计开发
  • 2025辽宁CSP-XL编程设计题与参考答案
  • 网站怎么做值班表郫都区规划建设局网站
  • 网站做查赚钱如何做简单的网站 域名邮箱
  • 网站建设与管理的书中国建设银行网站首页下载
  • Java—单例类(设计模式)
  • Linux 网络总结
  • 第一章-第三节-Java开发环境配置
  • 河南濮阳建设局网站天坛装修公司口碑怎么样
  • 关于Java回调函数的使用笔记
  • 贵州网站开发哪家好浙江网站推广公司
  • C语言——栈与队列
  • 企业门户网站源码商丘网站制作教程