diff --git a/docs/ai-reading/step4-architecture-layer.md b/docs/ai-reading/step4-architecture-layer.md index 2417eda..e1e394c 100644 --- a/docs/ai-reading/step4-architecture-layer.md +++ b/docs/ai-reading/step4-architecture-layer.md @@ -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层是否不依赖业务层 diff --git a/src/gateway/auth/auth.gateway.module.ts b/src/gateway/auth/auth.gateway.module.ts index c3b08b1..ea23bdd 100644 --- a/src/gateway/auth/auth.gateway.module.ts +++ b/src/gateway/auth/auth.gateway.module.ts @@ -29,11 +29,14 @@ import { LoginController } from './login.controller'; import { RegisterController } from './register.controller'; import { JwtAuthGuard } from './jwt_auth.guard'; import { AuthModule } from '../../business/auth/auth.module'; +import { LoginCoreModule } from '../../core/login_core/login_core.module'; @Module({ imports: [ // 导入业务层模块 AuthModule, + // 导入核心层模块(JwtAuthGuard需要LoginCoreService) + LoginCoreModule, ], controllers: [ // 网关层控制器