You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nest无法解析UserRepository依赖,登录用例跨模块访问问题

问题解决:NestJS跨模块访问Repository的依赖解析错误

错误原因

你遇到的Error: Nest can't resolve dependencies of the UserRepository (?)是因为AuthModule里重复创建了UserRepository的提供者,但这个新实例需要的UserModel(Mongoose模型)并没有在AuthModule的上下文里注册——只有UserModule导入了MongooseModule.forFeature来配置User模型,AuthModule自己没配置,所以Nest找不到这个依赖。

而UserController能正常访问是因为它属于UserModule,直接使用的是UserModule中已经配置好模型依赖的UserRepository实例。

最佳解决方案:复用UserModule导出的Repository

跨模块访问Repository的标准方式是在提供者模块(UserModule)导出Repository,然后在消费模块(AuthModule)导入该提供者模块,不需要重复创建提供者。具体修复步骤如下:

1. 调整UserModule:导出令牌形式的Repository(可选但推荐)

如果希望基于接口注入(符合DDD原则),可以在UserModule里把Repository注册为令牌提供者并导出:

// user.module.ts
import { Module } from '@nestjs/common';
import { UserController } from '../../controllers/user/user.controller';
import { MongooseModule } from '@nestjs/mongoose';
import UserRepository from '../../repository/mongoose/user/user.repository';
import { User, UserSchema } from '../../repository/mongoose/user/user.model';

@Module({
  imports: [
    MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
  ],
  controllers: [UserController],
  providers: [
    {
      provide: 'UserRepository', // 注册令牌
      useClass: UserRepository,
    },
  ],
  exports: ['UserRepository'], // 导出令牌,让其他模块能注入
})
export class UserModule {}

2. 清理AuthModule:移除重复的提供者

AuthModule不需要自己创建UserRepository、JwtService、BcryptService的提供者,因为:

  • UserRepository可以直接从UserModule导入使用
  • JwtModule已经全局注册,JwtService可直接注入
  • BcryptModule如果已经导出了BcryptService,导入后即可使用

修改后的AuthModule:

// auth.module.ts
import { Module } from '@nestjs/common';
import { AuthController } from '../../controllers/auth/auth.controller';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import LoginUseCase from '../../../usecase/auth/login.usecase';
import { JwtStrategy } from '../../common/strategies/jwt-strategy';
import { UserModule } from '../user/user.module';
import { BcryptModule } from '../bcrypt/bcrypt.module';

@Module({
  imports: [
    JwtModule.register({
      global: true,
      secret: process.env.JWT_SECRET,
      signOptions: { expiresIn: '1h' },
    }),
    PassportModule,
    UserModule, // 导入UserModule,就能使用它导出的Repository
    BcryptModule,
  ],
  controllers: [AuthController],
  providers: [LoginUseCase, JwtStrategy], // 移除重复的提供者
  exports: [LoginUseCase],
})
export class AuthModule {}

3. 调整LoginUseCase的注入(保持原有令牌注入方式)

因为我们在UserModule里注册了'UserRepository'令牌,所以LoginUseCase的注入代码不需要修改,保持原样即可:

// login.usecase.ts
constructor(
  @Inject('UserRepository')
  private userRepository: UserRepository,
  private jwtService: JwtService, // 直接注入全局的JwtService,不需要@Inject('JwtService')
  @Inject('BcryptService')
  private bcryptService: IBcryptService,
) {}

注:JwtService可以直接注入,不需要用@Inject('JwtService'),因为JwtModule注册的是类提供者。

额外优化:避免全局模块冗余

你的AppModule里重复注册了JwtModule和PassportModule,而AuthModule里已经注册了全局的JwtModule,所以可以把AppModule里的JwtModule和PassportModule移除,减少冗余。

核心总结

跨模块共享依赖的正确姿势是:

  • 提供者模块(如UserModule):注册依赖并导出它
  • 消费模块(如AuthModule):导入提供者模块,直接注入使用
  • 不要在消费模块里重复创建相同的提供者,否则会导致依赖上下文不一致

内容的提问来源于stack exchange,提问作者Lole

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 11:22:23