Spring Bean循环依赖问题:UserRepositoryImpl自注入异常排查
开发REST API应用时遇到Bean循环依赖错误,明明UserRepositoryImpl类里没有自身类型的字段,只依赖UserRepository接口和UserDomainConverter组件,但日志显示userRepositoryImpl存在循环依赖。
相关代码
UserRepositoryImpl类
@Repository public class UserRepositoryImpl { private final UserRepository repository; private final UserDomainConverter converter; @Autowired public UserRepositoryImpl(UserRepository repository, UserDomainConverter converter) { this.repository = repository; this.converter = converter; } //some methods }
UserDomainConverter类
@Component public class UserDomainConverter { //some methods }
UserRepository接口
@Repository public interface UserRepository extends JpaRepository<UserEntity, Long> { Optional<UserEntity> findByAuthToken(String authToken); Optional<UserEntity> findByNickname(String nickname); List<UserEntity> findUserEntitiesByIdIn(List<Long> idList); List<UserEntity> findUserEntitiesByNicknameIn(String nickname); }
错误日志
2022-09-14 23:56:06.379 INFO 21408 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] 2022-09-14 23:56:06.387 INFO 21408 --- [ main] ConditionEvaluationReportLoggingListener : Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2022-09-14 23:56:06.403 ERROR 21408 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPLICATION FAILED TO START *************************** Description: The dependencies of some of the beans in the application context form a cycle: userController defined in file [D:\IdeaProjects\sigma-internship\target\classes\spotylike\spotylike\controller\UserController.class] ↓ userService defined in file [D:\IdeaProjects\sigma-internship\target\classes\spotylike\spotylike\service\UserService.class] ┌─────┐ | userRepositoryImpl defined in file [D:\IdeaProjects\sigma-internship\target\classes\spotylike\spotylike\repository\impl\UserRepositoryImpl.class] └─────┘ Action: Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true. Process finished with exit code 1
问题根因
这是Spring Data JPA的默认命名规则导致的隐式循环依赖:
Spring Data JPA会自动为继承JpaRepository的接口生成代理实现类,默认规则是接口名+Impl。你给UserRepositoryImpl加了@Repository注解,Spring会把它当成UserRepository接口的自定义实现类。
当创建UserRepositoryImpl的Bean时,它需要注入UserRepository,此时Spring会返回你的UserRepositoryImpl本身(因为它被识别为接口的实现),于是形成了循环:UserRepositoryImpl依赖UserRepository,而UserRepository的实际实现就是UserRepositoryImpl。
修复方案
方案一:调整类名和结构(推荐)
修改自定义实现类的名称,避免和默认命名规则冲突,同时通过自定义接口分离方法:
// 定义自定义方法的接口 public interface UserRepositoryCustom { // 在这里声明你的自定义方法 } // 修改实现类名称并实现自定义接口 @Repository public class UserRepositoryCustomImpl implements UserRepositoryCustom { private final UserRepository repository; private final UserDomainConverter converter; @Autowired public UserRepositoryCustomImpl(UserRepository repository, UserDomainConverter converter) { this.repository = repository; this.converter = converter; } // 实现自定义方法 } // 让原接口继承自定义接口 @Repository public interface UserRepository extends JpaRepository<UserEntity, Long>, UserRepositoryCustom { // 原有查询方法 }
方案二:指定Bean名称
如果不想改类名,给UserRepositoryImpl的@Repository注解指定唯一名称,避免Spring把它识别为UserRepository的实现:
@Repository("customUserRepository") public class UserRepositoryImpl { // 类内容保持不变 }
这样Spring注入UserRepository时,会使用自动生成的代理类,而不是你的UserRepositoryImpl。
方案三:临时允许循环依赖(不推荐)
仅作为临时调试手段,在配置文件中添加:
# application.properties spring.main.allow-circular-references=true
这只是绕过问题,不是根本解决方式,不建议长期使用。
内容的提问来源于stack exchange,提问作者goozzy

