Skip to content
On this page

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;
  }
}

两种获取元数据的区别

获取元数据的两种方式有以下区别:

  1. Reflect.getMetadata 直接使用 Reflect API 读取元数据。
  2. this.reflector.get 利用了 Nest 提供的 Reflector 服务读取元数据。

Reflector 相比直接使用 Reflect API 的优势在于:

  1. 它封装并简化了元数据的获取方式。
  2. 它利用 Nest 的依赖注入系统,可以在不同模块和服务之间共享读取元数据的逻辑。
  3. 它内部做了缓存,可以提高获取元数据的性能。
  4. 它提供了一些额外的特性,比如可以基于类的继承层次读取元数据。

所以在 Nest 中,推荐使用 Reflector 而不是直接使用 Reflect API 来获取和读取元数据。

Reflector 隐藏了元数据读取的复杂性,提供了更优雅的方式来使用 Nest 的元数据系统。