将 JPA 存储库注入实现时的循环依赖

问题描述 投票:0回答:1

我最近在研究Spring Data JPA,遇到了一个奇怪的循环依赖错误。

以前我经常使用

MyBatis
,如下图。

// I often declare mapper first, and inject it to my persistence.

@Mapper
public interface MyBatisMapper {/* ... */}

/* ------------ */

@Repository
public class MyBatisRepo {
  private final MyBatisMapper mapper;

  public MyBatisRepo(MyBatisMapper mapper) {
    this.mapper = mapper;
  }
  
  /* ... */

}

所以我尝试了

JPA
这种方式,并面临循环依赖。

这是代码

JPA


  1. TestEntity
// entity just for test
@Entity
public class TestEntity {

    @Id
    private Long id;
}
  1. 存储库接口(合约)
// Persistence contracts
public interface TestRepo {

}
  1. JPA DAO
// 
public interface JPATestRepo extends JpaRepository<TestEntity, Long> {

}
  1. 存储库实现
@Repository
public class JPATestRepoImpl implements TestRepo {

    private final JPATestRepo jpaRepo;

    public JPATestRepoImpl(JPATestRepo jpaRepo) {
        this.jpaRepo = jpaRepo;
    }
}
  1. 错误
2024-10-19T19:46:00.760+09:00  WARN 66384 --- [testing] [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'JPATestRepoImpl' defined in file [/~~~/Desktop/Coding/testing/build/classes/java/main/core/testing/JPATestRepoImpl.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'JPATestRepoImpl': Requested bean is currently in creation: Is there an unresolvable circular reference?
2024-10-19T19:46:00.761+09:00  INFO 66384 --- [testing] [           main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2024-10-19T19:46:00.762+09:00  INFO 66384 --- [testing] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2024-10-19T19:46:00.807+09:00  INFO 66384 --- [testing] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2024-10-19T19:46:00.811+09:00  INFO 66384 --- [testing] [           main] .s.b.a.l.ConditionEvaluationReportLogger : 

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2024-10-19T19:46:00.825+09:00 ERROR 66384 --- [testing] [           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:

┌──->──┐
|  JPATestRepoImpl defined in file [/~~~/Desktop/Coding/testing/build/classes/java/main/core/testing/JPATestRepoImpl.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

在控制台中,它说

JPATestRepoImpl
本身有一个循环。

但是在上面的

JPATestRepoImpl
中,事实并非如此。 (至少我这么认为)

我已经重新启动、清理和重建应用程序,但都是一样的。

但是,如果我将

JPATestRepoImpl
重命名为另一个
(like TestRepoJPAImpl)
循环依赖就会像魔法一样消失......

Spring 或 JPA 的 bean 名称似乎相互冲突,但我不知道为什么会这样。

所以我想问一下我的源代码中是否真的存在循环依赖,或者如果没有则它来自哪里。如果 JPA 有任何政策,有相关文档吗?

java spring spring-boot spring-data-jpa circular-dependency
1个回答
0
投票

我认为这是 Spring 试图提供帮助的另一个例子。

它看到您有

JPATestRepo
JPATestRepoImpl
,并认为您想要一个实现另一个。

您可以看到,如果从构造函数中删除

JPATestRepo jpaRepo
并在某个类中注入
JPATestRepo
。你会看到注入对象的类名是
JPATestRepoImpl

我对这个天才决定背后的理由一无所知。我只能帮你在源代码中追踪造成这个惊喜的人。

© www.soinside.com 2019 - 2024. All rights reserved.