我最近在研究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
TestEntity
// entity just for test
@Entity
public class TestEntity {
@Id
private Long id;
}
// Persistence contracts
public interface TestRepo {
}
JPA DAO
//
public interface JPATestRepo extends JpaRepository<TestEntity, Long> {
}
@Repository
public class JPATestRepoImpl implements TestRepo {
private final JPATestRepo jpaRepo;
public JPATestRepoImpl(JPATestRepo jpaRepo) {
this.jpaRepo = jpaRepo;
}
}
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 有任何政策,有相关文档吗?
我认为这是 Spring 试图提供帮助的另一个例子。
它看到您有
JPATestRepo
和 JPATestRepoImpl
,并认为您想要一个实现另一个。
您可以看到,如果从构造函数中删除
JPATestRepo jpaRepo
并在某个类中注入 JPATestRepo
。你会看到注入对象的类名是JPATestRepoImpl
。
我对这个天才决定背后的理由一无所知。我只能帮你在源代码中追踪造成这个惊喜的人。