在 NestJS 中,Providers 用于定义、管理和注入各种服务和依赖。通常,Providers 是用来实现特定功能的服务、库或者工具类,在整个应用中可以被复用,并支持依赖注入。
1. Providers 的基本概念
在 NestJS 中,Providers 是被注入到其他组件中的类实例,例如 Service
、Repository
、Helper
等。通过使用 NestJS 的依赖注入机制,我们可以很方便地在一个组件中注入一个 Provider,而不用在组件中自己实例化依赖。每个 Provider 都可以在模块级别被定义和注册。
在 NestJS 中,Providers 的注册和声明通常是在模块文件(如 AppModule
或自定义模块)中完成的。
2. Providers 的定义
在 NestJS 中创建一个 Provider 时,通常步骤如下:
- 定义一个服务类。
- 在模块中将该服务注册为 Provider。
- 在其他类中注入该服务类,以使用其提供的功能。
3. 创建一个简单的 Provider
我们以一个简单的用户服务为例,展示如何创建和使用 Provider。
步骤 1:创建 UserService
在 UserService
中,我们定义一些管理用户的方法,例如获取用户列表或单个用户的信息。
// src/user/user.service.ts
import { Injectable } from '@nestjs/common';
@Injectable() // 1. 使用 @Injectable() 装饰器将 UserService 声明为 Provider
export class UserService {
private users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
findAll() {
return this.users;
}
findOne(id: number) {
return this.users.find(user => user.id === id);
}
}
步骤 2:在模块中注册 Provider
我们需要在模块文件中将 UserService
注册为 Provider,这样其他组件才能使用它。NestJS 模块文件默认包含一个 providers
数组,用于声明模块的 Providers。
// src/user/user.module.ts
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
@Module({
providers: [UserService], // 2. 将 UserService 注册为 Module 的 Provider
exports: [UserService], // 3. 使用 exports 以便在其他模块中使用此 Provider
})
export class UserModule {}
通过将 UserService
添加到 providers
和 exports
数组中,我们将它注册为一个可注入的 Provider,并允许其他模块访问。
这里也可以使用一个对象的方式进行 providers :
providers: [{
provide:'User',
userClass: UserService
}],
然后使用需要使用 @inject 装饰器:
@Inject("User") private readonly userService: UserService
此外,可以自定义注入值:
providers: [{
provide: "User",
useClass: UserService
}, {
provide: "t1",
useValue: ['t1', 'blg', 'tes']
}
步骤 3:在其他服务中注入并使用 Provider
接下来,我们在另一个服务或控制器中使用 UserService
。我们可以通过构造函数注入的方式使用 UserService
。
// src/app/app.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
import { UserService } from '../user/user.service';
@Controller('users')
export class AppController {
constructor(private readonly userService: UserService) {} // 4. 通过构造函数注入 UserService
@Get()
findAll() {
return this.userService.findAll(); // 调用 UserService 的 findAll 方法
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.userService.findOne(Number(id)); // 调用 UserService 的 findOne 方法
}
}
4. 运行逻辑说明
当客户端访问 /users
路由时,AppController
将调用 UserService
的 findAll
方法并返回所有用户数据。同样地,访问 /users/:id
时,将调用 findOne
方法并返回指定 ID 的用户。
通过这种方式,UserService
的实例可以在任何需要的地方注入和复用,而不需要重复创建实例。
5. Provider 的作用域
在 NestJS 中,Provider 的作用域包括三种:
- 默认作用域:Provider 在整个应用程序生命周期内是单例的。
- 请求作用域:Provider 在每个请求内是唯一的实例。这种方式适合处理和请求相关的状态。
- 瞬时作用域:每次注入时都会创建一个新实例。这适合需要短暂存在的对象。
@Injectable({ scope: Scope.REQUEST }) // 将作用域设置为请求作用域
export class UserService {
// 你的服务逻辑
}
6. Provider 的工厂模式
除了直接定义类作为 Provider,NestJS 还支持使用工厂模式定义 Provider。工厂 Provider 是通过函数生成实例,特别适合初始化需要复杂配置的对象。
// src/app.providers.ts
import { Provider } from '@nestjs/common';
export const ConfigProvider: Provider = {
provide: 'CONFIG',
useFactory: () => ({
appName: 'MyApp',
version: '1.0.0',
}),
};
这里使用的函数也可以使用异步函数。
在模块中注册该 Provider:
// src/app/app.module.ts
import { Module } from '@nestjs/common';
import { ConfigProvider } from './app.providers';
@Module({
providers: [ConfigProvider], // 注册工厂 Provider
})
export class AppModule {}
在其他服务中注入:
import { Inject, Injectable } from '@nestjs/common';
@Injectable()
export class SomeService {
constructor(@Inject('CONFIG') private config: any) {} // 通过 @Inject 注入工厂 Provider
printConfig() {
console.log(this.config); // 输出 { appName: 'MyApp', version: '1.0.0' }
}
}
总结
在 NestJS 中,Providers 是创建、管理和注入服务、库的核心。通过使用 @Injectable()
装饰器、模块化管理和依赖注入,我们可以轻松创建可复用、易测试的服务层逻辑。同时,通过作用域和工厂模式,我们可以根据不同的场景和需求,灵活定义和配置 Providers,从而使应用更加灵活和模块化。