@@ -442,6 +442,190 @@ export class UsersBusinessService {
}
```
## 🔧 NestJS依赖注入检查( 重要)
### 依赖注入完整性检查
**在NestJS中, 如果一个类( 如Guard、Service、Controller) 需要注入其他服务, 必须确保该服务在模块的imports中可访问。**
### 常见依赖注入问题
``` typescript
// ❌ 错误: JwtAuthGuard需要LoginCoreService, 但模块未导入LoginCoreModule
@Module ( {
imports : [
AuthModule , // AuthModule虽然导入了LoginCoreModule, 但没有重新导出
] ,
providers : [
JwtAuthGuard , // 错误: 无法注入LoginCoreService
] ,
} )
export class AuthGatewayModule { }
@Injectable ( )
export class JwtAuthGuard {
constructor (
private readonly loginCoreService : LoginCoreService , // 注入失败!
) { }
}
// ✅ 正确方案1: 直接导入需要的Core模块
@Module ( {
imports : [
AuthModule ,
LoginCoreModule , // 直接导入, 使LoginCoreService可用
] ,
providers : [
JwtAuthGuard , // 现在可以成功注入LoginCoreService
] ,
} )
export class AuthGatewayModule { }
// ✅ 正确方案2: 在中间模块重新导出
@Module ( {
imports : [ LoginCoreModule ] ,
exports : [ LoginCoreModule ] , // 重新导出, 让导入AuthModule的模块也能访问
} )
export class AuthModule { }
```
### 依赖注入检查规则
#### 1. 检查Provider的构造函数依赖
``` typescript
// 对于每个Provider( Service、Guard、Interceptor等)
@Injectable ( )
export class SomeGuard {
constructor (
private readonly serviceA : ServiceA , // 依赖1
private readonly serviceB : ServiceB , // 依赖2
) { }
}
// 检查清单:
// ✓ ServiceA是否在当前模块的imports中?
// ✓ ServiceB是否在当前模块的imports中?
// ✓ 如果不在, 是否需要添加对应的Module到imports?
```
#### 2. 检查Module的导出完整性
``` typescript
// ❌ 错误:导入了模块但没有导出,导致上层模块无法访问
@Module ( {
imports : [ LoginCoreModule ] ,
providers : [ LoginService ] ,
exports : [ LoginService ] , // 只导出了LoginService, 没有导出LoginCoreModule
} )
export class AuthModule { }
// 如果上层模块需要直接使用LoginCoreService:
@Module ( {
imports : [ AuthModule ] , // 无法访问LoginCoreService
providers : [ JwtAuthGuard ] , // JwtAuthGuard需要LoginCoreService, 会失败
} )
export class AuthGatewayModule { }
// ✅ 正确: 根据需要导出Module
@Module ( {
imports : [ LoginCoreModule ] ,
providers : [ LoginService ] ,
exports : [
LoginService ,
LoginCoreModule , // 导出Module, 让上层也能访问
] ,
} )
export class AuthModule { }
```
#### 3. 检查跨层依赖的模块导入
``` typescript
// Gateway层的Guard直接依赖Core层Service的情况
@Injectable ( )
export class JwtAuthGuard {
constructor (
private readonly loginCoreService : LoginCoreService , // 直接依赖Core层
) { }
}
// 检查清单:
// ✓ AuthGatewayModule是否导入了LoginCoreModule?
// ✓ 如果通过AuthModule间接导入, AuthModule是否导出了LoginCoreModule?
// ✓ 是否符合架构分层原则( Gateway可以直接依赖Core用于技术实现) ?
```
### 依赖注入检查步骤
1. **扫描所有Injectable类 **
- 找出所有使用@Injectable ()装饰器的类
- 包括Service、Guard、Interceptor、Pipe等
2. **分析构造函数依赖 **
- 检查每个类的constructor参数
- 列出所有需要注入的服务
3. **检查Module的imports **
- 确认每个依赖的服务是否在Module的imports中
- 检查imports的Module是否导出了需要的服务
4. **验证依赖链完整性 **
- 如果A模块导入B模块, B模块导入C模块
- 确认A模块是否能访问C模块的服务( 取决于B是否导出C)
5. **检查常见错误模式 **
- Guard/Interceptor依赖Service但模块未导入
- 中间模块导入但未导出,导致上层无法访问
- 循环依赖问题
### 依赖注入错误识别
#### 典型错误信息
```
Nest can't resolve dependencies of the JwtAuthGuard (?).
Please make sure that the argument LoginCoreService at index [0]
is available in the AuthGatewayModule context.
```
#### 错误分析流程
```
1. 识别问题类: JwtAuthGuard
2. 识别缺失依赖: LoginCoreService( 索引0)
3. 识别所在模块: AuthGatewayModule
4. 检查解决方案:
├─ LoginCoreService在哪个Module中提供?
│ └─ 答: LoginCoreModule
├─ AuthGatewayModule是否导入了LoginCoreModule?
│ └─ 否 → 需要添加到imports
└─ 如果通过其他Module间接导入, 该Module是否导出了LoginCoreModule?
└─ 否 → 需要在中间Module的exports中添加
```
### 依赖注入最佳实践
``` typescript
// ✅ 推荐:明确的依赖关系
@Module ( {
imports : [
// 业务层模块
AuthModule ,
// 直接需要的核心层模块( 用于Guard等技术组件)
LoginCoreModule ,
] ,
controllers : [ LoginController ] ,
providers : [ JwtAuthGuard ] ,
exports : [ JwtAuthGuard ] ,
} )
export class AuthGatewayModule { }
// ✅ 推荐:完整的导出链
@Module ( {
imports : [ LoginCoreModule , UsersModule ] ,
providers : [ LoginService ] ,
exports : [
LoginService , // 导出自己的服务
LoginCoreModule , // 导出依赖的模块(如果上层需要)
] ,
} )
export class AuthModule { }
```
## 🔍 检查执行步骤
1. **识别当前模块的层级 **
@@ -475,7 +659,14 @@ export class UsersBusinessService {
- Core层是否只包含技术实现
- 是否有跨层职责混乱
6. **检查依赖关系 **
6. * * 🔥 检查依赖注入完整性(关键步骤) **
- 扫描所有Injectable类的构造函数依赖
- 检查Module的imports是否包含所有依赖的Module
- 验证中间Module是否正确导出了需要的服务
- 确认依赖链的完整性和可访问性
- 识别并修复常见的依赖注入错误
7. **检查依赖关系 **
- Gateway层是否只依赖Business层
- Business层是否只依赖Core层
- Core层是否不依赖业务层