发现服务
由 @nestjs/core
包提供的 DiscoveryService
是一个强大的工具,允许开发者动态检查和检索 NestJS 应用程序中的提供者、控制器和其他元数据。这在构建依赖运行时自省的插件、装饰器或高级功能时特别有用。通过利用 DiscoveryService
,开发者可以创建更灵活和模块化的架构,实现应用程序中的自动化和动态行为。
快速开始
在使用 DiscoveryService
之前,您需要在打算使用它的模块中导入 DiscoveryModule
。这确保了该服务可用于依赖注入。以下是在 NestJS 模块中配置的示例:
import { Module } from '@nestjs/common';
import { DiscoveryModule } from '@nestjs/core';
import { ExampleService } from './example.service';
@Module({
imports: [DiscoveryModule],
providers: [ExampleService],
})
export class ExampleModule {}
模块设置完成后,DiscoveryService
可以被注入到任何需要动态发现的提供者或服务中。
@@filename(example.service)
@Injectable()
export class ExampleService {
constructor(private readonly discoveryService: DiscoveryService) {}
}
发现提供者和控制器
DiscoveryService
的一个关键能力是检索应用中所有已注册的提供者。这对于基于特定条件动态处理提供者非常有用。以下代码片段展示了如何访问所有提供者:
const providers = this.discoveryService.getProviders();
console.log(providers);
每个提供者对象包含其实例、令牌和元数据等信息。同样,如果需要检索应用中所有已注册的控制器,可以通过以下方式实现:
const controllers = this.discoveryService.getControllers();
console.log(controllers);
该特性对于需要动态处理控制器的场景特别有用,例如分析跟踪或自动注册机制。
提取元数据
除了发现提供者和控制器外,DiscoveryService
还能获取附加在这些组件上的元数据。这对于处理在运行时存储元数据的自定义装饰器特别有价值。
例如,考虑使用自定义装饰器为提供者标记特定元数据的情况:
import { DiscoveryService } from '@nestjs/core';
export const FeatureFlag = DiscoveryService.createDecorator();
将此装饰器应用于服务后,可以存储后续可查询的元数据:
import { Injectable } from '@nestjs/common';
import { FeatureFlag } from './custom-metadata.decorator';
@Injectable()
@FeatureFlag('experimental')
export class CustomService {}
当以这种方式将元数据附加到提供者后,DiscoveryService
可以轻松根据分配的元数据筛选提供者。以下代码片段演示了如何检索标记了特定元数据值的提供者:
const providers = this.discoveryService.getProviders();
const [provider] = providers.filter(
(item) =>
this.discoveryService.getMetadataByDecorator(FeatureFlag, item) ===
'experimental',
);
console.log(
'Providers with the "experimental" feature flag metadata:',
provider,
);
结论
DiscoveryService
是一个多功能且强大的工具,能够在 NestJS 应用程序中实现运行时内省。通过支持动态发现提供者、控制器和元数据,它在构建可扩展框架、插件和自动化驱动功能方面发挥着关键作用。无论是需要扫描和处理提供者、提取元数据进行高级处理,还是创建模块化和可扩展的架构,DiscoveryService
都为实现这些目标提供了高效且结构化的方法。