Reflect 和 Metadat
Reflect.api
对类,实例,方法,属性设置元数据(保存在对应的类或者实例的内部属性[[metadata]]上)
typescript
Reflect.defineMetadata(metadataKey, metadataValue, target);
Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey);
let result = Reflect.getMetadata(metadataKey, target);
let result = Reflect.getMetadata(metadataKey, target, propertyKey);
Nest 中的装饰器原理
通过装饰器给 class 或者对象添加 metadata,并且开启 ts 的 emitDecoratorMetadata 来自动添加类型相关的 metadata,然后运行的时候通过这些元数据来实现依赖的扫描,对象的创建等等功能。
基本使用
typescript
import {
Controller,
Get,
UseGuards,
SetMetadata,
} from '@nestjs/common';
import { AppService } from './app.service';
import { AaaFilter } from './aaa.filter';
import { AaaGuard } from './aaa.guard';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
@UseGuards(AaaGuard)
@SetMetadata('aaa', ['admin'])
getHello(): string {
return this.appService.getHello();
}
}
typescript
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
@Injectable()
export class AaaGuard implements CanActivate {
constructor(private readonly reflecotr: Reflector) {}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
console.log(Reflect.getMetadata('aaa', context.getHandler()));
console.log(this.reflecotr.get('aaa', context.getHandler()));
return true;
}
}
两种获取元数据的区别
获取元数据的两种方式有以下区别:
- Reflect.getMetadata 直接使用 Reflect API 读取元数据。
- this.reflector.get 利用了 Nest 提供的 Reflector 服务读取元数据。
Reflector 相比直接使用 Reflect API 的优势在于:
- 它封装并简化了元数据的获取方式。
- 它利用 Nest 的依赖注入系统,可以在不同模块和服务之间共享读取元数据的逻辑。
- 它内部做了缓存,可以提高获取元数据的性能。
- 它提供了一些额外的特性,比如可以基于类的继承层次读取元数据。
所以在 Nest 中,推荐使用 Reflector 而不是直接使用 Reflect API 来获取和读取元数据。
Reflector 隐藏了元数据读取的复杂性,提供了更优雅的方式来使用 Nest 的元数据系统。