NestJS提供者(Provider) #
什么是提供者? #
提供者是NestJS中的一个核心概念。提供者是一个被@Injectable()装饰器装饰的类,它可以被注入到其他类中(如控制器、其他服务等)。提供者通常是服务(Service),但也可以是仓库、工厂、助手等。
基本服务 #
创建服务 #
使用CLI创建服务:
bash
nest g service users
生成的代码:
typescript
import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {}
完整的服务示例 #
typescript
import { Injectable } from '@nestjs/common';
import { User } from './interfaces/user.interface';
@Injectable()
export class UsersService {
private readonly users: User[] = [];
create(user: User) {
this.users.push(user);
}
findAll(): User[] {
return this.users;
}
findOne(id: number): User {
return this.users.find(user => user.id === id);
}
update(id: number, user: User) {
const index = this.users.findIndex(u => u.id === id);
if (index !== -1) {
this.users[index] = { ...this.users[index], ...user };
}
return this.users[index];
}
remove(id: number) {
const index = this.users.findIndex(u => u.id === id);
if (index !== -1) {
this.users.splice(index, 1);
}
}
}
注册提供者 #
提供者需要在模块中注册:
typescript
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
@Module({
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
依赖注入 #
构造函数注入 #
typescript
import { Controller } from '@nestjs/common';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get()
findAll() {
return this.usersService.findAll();
}
}
服务间依赖 #
typescript
@Injectable()
export class UsersService {
constructor(
private readonly databaseService: DatabaseService,
private readonly loggerService: LoggerService,
) {}
}
提供者注册方式 #
类提供者 #
最常用的方式:
typescript
providers: [UsersService]
// 等价于
providers: [
{
provide: UsersService,
useClass: UsersService,
},
]
值提供者 #
使用现有值:
typescript
import { User } from './user.mock';
providers: [
{
provide: 'MOCK_USER',
useValue: new User(),
},
]
工厂提供者 #
使用工厂函数动态创建:
typescript
providers: [
{
provide: 'DATABASE_CONNECTION',
useFactory: (configService: ConfigService) => {
return createConnection({
host: configService.get('DB_HOST'),
port: configService.get('DB_PORT'),
});
},
inject: [ConfigService],
},
]
别名提供者 #
为现有提供者创建别名:
typescript
providers: [
UsersService,
{
provide: 'UserServiceAlias',
useExisting: UsersService,
},
]
自定义提供者Token #
使用字符串Token #
typescript
providers: [
{
provide: 'CONFIG_OPTIONS',
useValue: { apiKey: 'xxx', timeout: 5000 },
},
]
// 注入时使用@Inject
constructor(
@Inject('CONFIG_OPTIONS') private options: ConfigOptions,
) {}
使用Symbol Token #
typescript
export const CONFIG_OPTIONS = Symbol('CONFIG_OPTIONS');
providers: [
{
provide: CONFIG_OPTIONS,
useValue: { apiKey: 'xxx' },
},
]
// 注入
constructor(
@Inject(CONFIG_OPTIONS) private options: ConfigOptions,
) {}
使用InjectionToken(TypeScript) #
typescript
import { InjectionToken } from '@nestjs/core';
export const CONFIG_OPTIONS = new InjectionToken<ConfigOptions>('CONFIG_OPTIONS');
异步提供者 #
返回Promise的工厂函数:
typescript
providers: [
{
provide: 'ASYNC_CONNECTION',
useFactory: async () => {
const connection = await createConnection();
return connection;
},
},
]
提供者示例 #
数据库连接提供者 #
typescript
import { Injectable, OnModuleDestroy } from '@nestjs/common';
import { createConnection, Connection } from 'mysql2/promise';
@Injectable()
export class DatabaseService implements OnModuleDestroy {
private connection: Connection;
async onModuleInit() {
this.connection = await createConnection({
host: 'localhost',
user: 'root',
database: 'test',
});
}
async onModuleDestroy() {
await this.connection.end();
}
async query(sql: string, params?: any[]) {
const [rows] = await this.connection.execute(sql, params);
return rows;
}
}
缓存服务 #
typescript
import { Injectable } from '@nestjs/common';
@Injectable()
export class CacheService {
private cache = new Map<string, { value: any; expire: number }>();
set(key: string, value: any, ttl: number = 60000) {
this.cache.set(key, {
value,
expire: Date.now() + ttl,
});
}
get<T>(key: string): T | null {
const item = this.cache.get(key);
if (!item) return null;
if (Date.now() > item.expire) {
this.cache.delete(key);
return null;
}
return item.value as T;
}
delete(key: string) {
this.cache.delete(key);
}
clear() {
this.cache.clear();
}
}
日志服务 #
typescript
import { Injectable, LoggerService, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.TRANSIENT })
export class CustomLoggerService implements LoggerService {
private context?: string;
setContext(context: string) {
this.context = context;
}
log(message: string) {
console.log(`[${this.context}] ${message}`);
}
error(message: string, trace?: string) {
console.error(`[${this.context}] ERROR: ${message}`);
if (trace) console.error(trace);
}
warn(message: string) {
console.warn(`[${this.context}] WARN: ${message}`);
}
debug(message: string) {
console.debug(`[${this.context}] DEBUG: ${message}`);
}
verbose(message: string) {
console.log(`[${this.context}] VERBOSE: ${message}`);
}
}
配置服务 #
typescript
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class AppConfigService {
constructor(private configService: ConfigService) {}
get databaseHost(): string {
return this.configService.get<string>('DATABASE_HOST');
}
get databasePort(): number {
return this.configService.get<number>('DATABASE_PORT', 3306);
}
get jwtSecret(): string {
return this.configService.get<string>('JWT_SECRET');
}
get isDevelopment(): boolean {
return this.configService.get<string>('NODE_ENV') === 'development';
}
get isProduction(): boolean {
return this.configService.get<string>('NODE_ENV') === 'production';
}
}
仓库模式 #
typescript
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './entities/user.entity';
@Injectable()
export class UsersRepository {
constructor(
@InjectRepository(User)
private readonly repository: Repository<User>,
) {}
async findAll(): Promise<User[]> {
return this.repository.find();
}
async findOne(id: number): Promise<User | null> {
return this.repository.findOne({ where: { id } });
}
async create(userData: Partial<User>): Promise<User> {
const user = this.repository.create(userData);
return this.repository.save(user);
}
async update(id: number, userData: Partial<User>): Promise<User | null> {
await this.repository.update(id, userData);
return this.findOne(id);
}
async delete(id: number): Promise<void> {
await this.repository.delete(id);
}
}
提供者作用域 #
typescript
import { Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class RequestScopedService {
private requestId: string;
setRequestId(id: string) {
this.requestId = id;
}
getRequestId(): string {
return this.requestId;
}
}
| 作用域 | 说明 | 性能影响 |
|---|---|---|
DEFAULT |
单例,应用生命周期内唯一 | 无 |
REQUEST |
每个请求创建新实例 | 中等 |
TRANSIENT |
每次注入创建新实例 | 较高 |
可选提供者 #
typescript
import { Injectable, Optional } from '@nestjs/common';
@Injectable()
export class HttpService {
constructor(
@Optional()
private readonly logger?: LoggerService,
) {}
request(url: string) {
this.logger?.log(`Requesting ${url}`);
}
}
总结 #
本章深入学习了NestJS提供者:
- 服务的创建和使用
- 提供者的注册方式
- 自定义提供者Token
- 工厂提供者和异步提供者
- 仓库模式的实现
接下来,让我们学习 依赖注入。
最后更新:2026-03-28