1. 先从一个问题说起
想象一下,你是一家公司的老板。
公司刚成立的时候,你需要亲自管理所有员工:
javascript
// 手动创建和组装所有对象
const config = new Config({ username: 'xxx', password: 'xxx' });
const dataSource = new DataSource(config);
const repository = new Repository(dataSource);
const service = new Service(repository);
const controller = new Controller(service);
累不累?每次有新项目,你都要从头梳理一遍:谁依赖谁?谁先创建?谁后创建?
这就是后端系统的痛点 ------ 对象之间的依赖关系太复杂了。
2. 解决方案: IOC 机制
后来你想了个办法:在每个员工身上贴个标签,说明他需要谁来配合工作。
比如:
- 客服(Controller):我需要一个服务员(Service)来配合
- 服务员(Service):我需要一个仓管(Repository)来配合
- 仓管(Repository):我需要一个数据库连接(DataSource)来配合
然后公司有个自动分配系统,读取这些标签,自动帮你创建和组装好所有员工。
这就是 IoC(控制反转):
本来需要你自己手动 new 对象、组装关系 现在只需要声明依赖谁,系统自动帮你创建和组装
3. Nest 怎么用?用"公司架构"来理解
Nest 就是这家"公司",它有三层架构:
typescript
@Module({
controllers: [AppController], // 领导
providers: [AppService] // 服务台
})
export class AppModule {}
① Controller = 领导
作用:接收客户请求(比如接口调用),然后指挥下属干活
规则:只能指挥服务台,不能被服务台指挥
typescript
@Controller()
export class AppController {
// 领导只需要告诉服务台要什么,结果自然有人送来
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello(); // 领导发话,服务台去办
}
}
简单理解:领导只负责接单发号施令,不亲自干活。
② Service = 服务台
作用:真正干活的人,写业务逻辑、查数据库、处理数据
规则:既可以被领导指挥,也可以指挥别的服务台
typescript
@Injectable()
export class AppService {
// 服务台 A 可以指挥服务台 B
constructor(private readonly userService: UserService) {}
getHello(): string {
return 'Hello! ' + this.userService.getUserName();
}
}
简单理解:服务台既能被领导使唤,也能使唤别的服务台。
③ Module = 部门
作用:把相关的领导和员工打包在一起,方便管理
4. 部门内部怎么调用?(同部门)
假设你是**用户部门(UserModule)**的员工:
typescript
@Module({
controllers: [UserController], // 用户部门的领导
providers: [UserService] // 用户部门的服务台
})
export class UserModule {}
用户部门的领导指挥用户部门的服务台,同一个部门内,直接用:
typescript
@Controller()
export class UserController {
constructor(private readonly userService: UserService) {}
// 同部门,直接叫下属干活
}
一句话:同部门调用,不需要任何额外操作,直接用。
5. 跨部门怎么调用?(不同模块)
现在情况变了:你是用户部门(UserModule),但你需要用**日志部门(LoggerModule)**的服务。
核心规则:2 步走
第 1 步:日志部门必须「把服务放出来」
typescript
@Module({
providers: [LoggerService], // 日志部门有这个服务
exports: [LoggerService], // 同意对外开放使用
})
export class LoggerModule {}
相当于:公司在门口挂了个牌子,写着"本部门提供 XXX 服务"。
第 2 步:用户部门「申请使用」
typescript
@Module({
imports: [LoggerModule], // 申请使用日志部门的服务
controllers: [UserController],
providers: [UserService]
})
export class UserModule {}
相当于:你提交了申请,HR 批准你可以去日志部门串门。
第 3 步:直接调用
typescript
@Injectable()
export class UserService {
constructor(private logger: LoggerService) {}
createUser() {
this.logger.log('创建用户'); // 直接用!
}
}
相当于:申请通过后,你就可以直接去日志部门找对应的员工帮忙了。
6. 总结:记住这个比喻
| 角色 | Nest 概念 | 职责 |
|---|---|---|
| 领导 | @Controller | 接收请求,发号施令 |
| 服务台 | @Injectable | 真正干活 |
| 部门 | @Module | 打包管理 |
调用规则:
- 同部门:直接用
- 跨部门:对方 exports → 我 imports → 直接用
7. 最后
Nest 的 IoC 机制,说白了就是:
领导负责发号施令,服务台负责干活。部门内部直接用,跨部门先申请再用。