定义
Provider 只是一个用 @Injectable() 装饰器注释的类,用于在 NestJS 中实现依赖注入
当 NestJS 启动时,会扫描所有 Provider,并将其注册到 IoC 容器中
当其他组件需要该 Provider 时,组件通过类型从 IoC 容器中获取该 Provider,IoC 容器会自动解析依赖、创建实例、并将其注入到该组件中
基本用法
app.service.ts 定义一个 Provider
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}app.module.ts 定义一个 Module,将 AppService Provider 注册到 IoC 容器中,同时将 AppController 注册到 Module 中
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}app.controller.ts 定义一个 Controller,将 AppService Provider 注入到该 Controller 中
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
// 构造函数注入 AppService Provider
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}自定义 名称
在app.module.ts中,可以自定义 Provider 的名称,原来的基本用法就是语法糖,实际传入的参数是一个对象
@Module({
controllers: [AppController],
providers: [{
provide: 'APP_SERVICE',
useClass: AppService,
}],
})
export class AppModule {}使用了自定义名称的 Provider,需要在构造函数中使用 @Inject 装饰器注入该 Provider ,并指定自定义名称
@Controller()
export class AppController {
// 构造函数注入 AppService Provider
constructor(@Inject('APP_SERVICE') private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}自定义 注入值
通过useValue属性 可以在 Provider 中定义自定义的注入值,用于在构造函数中注入非 Provider 类型的值
@Module({
controllers: [AppController],
providers: [{
provide: 'str',
useValue: 'Hello World!',
}],
})
export class AppModule {}可以在构造函数中使用 @Inject 装饰器注入自定义的注入值
@Controller()
export class AppController {
// 构造函数注入 str Provider
constructor(@Inject('str') private readonly str: string) {}
}工厂模式
工厂模式是一种设计模式,用于创建对象的实例
在 NestJS 中,可以通过工厂模式 来动态创建 Provider 的实例/服务
app.service.ts 定义一个 Provider,用于判断是否成功
@Injectable()
export class AppService {
isOk(): boolean {
return true;
}
}app.module.ts 定义一个 Module
@Module({
controllers: [AppController],
providers: [{
provide: 'FactoryMod',
inject: [AppService], // 注入 AppService Provider, 做工厂模式的依赖
useFactory: (appService: AppService) => {
// 根据其他的 业务逻辑 来动态创建实例/服务
if (appService.isOk()) {
return 'FactoryMod Ok';
} else {
return 'FactoryMod Failed';
}
},
},],
})
export class AppModule {}app.controller.ts 定义一个 Controller,将 FactoryMod Provider 注入到该 Controller 中
@Controller()
export class AppController {
// 构造函数注入 FactoryMod Provider
constructor(@Inject('FactoryMod') private readonly factoryMod: string) {}
}使用 JwtModule 工厂模式
在开启了 monorepo模式的nest项目中使用Jwt认证公共配置
文件:./libs/shared/src/shared.module.ts
import { Global, Module } from '@nestjs/common';
import { SharedService } from './shared.service';
import { PrismaModule } from './prisma/prisma.module';
import { ResponseModule } from './response/response.module';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { JwtModule } from '@nestjs/jwt';
@Global()
@Module({
providers: [SharedService],
exports: [SharedService, PrismaModule, ResponseModule, JwtModule],
imports: [
// ORM 模块,用于数据库数据库操作
PrismaModule,
// 统一响应模块,用于处理响应
ResponseModule,
// 配置模块,用于加载环境变量
ConfigModule.forRoot({
envFilePath: '.env',
isGlobal: true,
}),
// 异步 JWT 模块,用于认证
JwtModule.registerAsync({
/** 引入配置模块 */
imports: [ConfigModule],
/** 注入配置服务 */
inject: [ConfigService],
/** 配置工厂函数 */
useFactory: (configService: ConfigService) => {
// 根据配置动态创建 JWT 模块的实例
return {
global: true, // 全局模块
secret: configService.get('SECRET_KEY'), // 密钥
signOptions: { expiresIn: '1h' }, // 过期时间为1小时
};
},
}),
],
})
export class SharedModule {}在某个微服务的 auth 模块中,引入 SharedModule,即可使用 JwtModule 工厂模式
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { SharedModule } from '@libs/shared';
@Module({
/** 引入共享模块: 包含 JwtModule 配置*/
imports: [SharedModule],
/** 引入服务 */
providers: [AuthService],
/** 导出服务 */
exports: [AuthService],
})
export class AuthModule {}
声明一个 Provider AuthService,专门用于生成和验证 JWT 令牌
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthService {
constructor(private jwtService: JwtService) {}
generateToken(payload: TokenPayload): Token {
return {
accessToken: this.jwtService.sign<TypedTokenPayload>({
...payload,
tokenType: 'access',
}),
refreshToken: this.jwtService.sign<TypedTokenPayload>(
{
...payload,
tokenType: 'refresh',
},
{
expiresIn: '7d',
},
),
};
}
verifyToken(token: string): TypedTokenPayload | null {
try {
// 这个JwtService.verify 方法会直接抛出错误,需要手动捕获异常
return this.jwtService.verify<TypedTokenPayload>(token);
} catch (error) {
return null;
}
}
}异步模式
useFactory 方法可以异步创建 Provider 的实例/服务
但即使返回了 Promise,Nest 解析 Promise 后,会将 Promise 解析后的结果作为 Provider 的实例/服务,而不是直接返回 Promise
{
provide: 'FactoryMod',
inject: [AppService], // 使用类作为令牌,与注册方式一致
useFactory: (appService: AppService) => {
if (appService.isOk()) {
return new Promise((resolve) =>
setTimeout(() => resolve('FactoryMod Ok'), 1000),
);
} else {
return new Promise((resolve) =>
setTimeout(() => resolve('FactoryMod Failed'), 1000),
);
}
},
},总结
Provider 是 NestJS 依赖注入的基础,用
@Injectable()标记支持自定义名称、自定义值、工厂模式、异步创建等多种用法
配合
@Inject()可以灵活注入各种依赖工厂模式特别适合需要根据配置动态创建实例的场景(如 JWT 配置)
Nestjs-Provider
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。



评论交流
欢迎留下你的想法