Java 应用程序上下文中某些bean的依赖关系形成一个循环

Java 应用程序上下文中某些bean的依赖关系形成一个循环,java,spring,spring-boot,spring-data-jpa,Java,Spring,Spring Boot,Spring Data Jpa,我正在使用JPA开发SpringBootV1.4.2.RELEASE应用程序 我定义了存储库接口和实现 积极的 @Repository public interface ARepository extends CrudRepository<A, String>, ARepositoryCustom, JpaSpecificationExecutor<A> { } 我的应用程序不会以以下消息启动: *************************** APPLICATI

我正在使用JPA开发SpringBootV1.4.2.RELEASE应用程序

我定义了存储库接口和实现

积极的

@Repository
public interface ARepository extends CrudRepository<A, String>, ARepositoryCustom, JpaSpecificationExecutor<A> {
}
我的应用程序不会以以下消息启动:

*************************** APPLICATION FAILED TO START *************************** Description: The dependencies of some of the beans in the application context form a cycle: | aRepositoryImpl └─────┘ *************************** 应用程序无法启动 *************************** 说明: 应用程序上下文中某些bean的依赖关系形成一个循环: |积极的 └─────┘ 我遵循了书中描述的所有步骤

请帮忙


Laurent

我已经测试了你的源代码,发现了一些棘手的问题

首先,使用您的源代码,我得到了以下错误:

There is a circular dependency between 1 beans in the application context:
- ARepositoryImpl (field private test.ARepository test.ARepositoryImpl.aRepository)
- aRepositoryImpl
然后,我猜Spring“混淆”了
ARepository
(JPA存储库)和
ARepositoryImpl
(自定义存储库)。 因此,我建议您
ARepository
重命名为其他名称,例如
BRepository
。如果我重新命名类名,它会起作用

根据弹簧数据的官方文件():

这些类需要遵循命名约定,将名称空间元素的属性repository impl后缀追加到找到的存储库接口名称此后缀默认为Impl

@Repository
public class ARepositoryImpl implements ARepositoryCustom {
    @Autowired
    private ARepository aRepository;
    @Override
    public Page<A> findA(findAForm form, Pageable pageable) {
        return aRepository.findAll(
                where(ASpecs.codeLike(form.getCode()))
                .and(ASpecs.labelLike(form.getLabel()))
                .and(ASpecs.isActive()),
                pageable);
    }
}
@Service
public class AServiceImpl implements AService {
    private ARepository aRepository;
    public AServiceImpl(ARepository aRepository) {
        super();
        this.aRepository = aRepository;
    }
    ...
}

对于原始问题,有一个简单的解决方案: 只需从ARepositoryCustom和ARepositoryImpl中删除@Repository。 保留所有命名和接口/类层次结构。他们都很好。

使用
@Lazy

打破循环的一个简单方法是说Spring惰性地初始化一个bean。也就是说:它不会完全初始化bean,而是创建一个代理将其注入到另一个bean中。注入的bean只有在第一次需要时才能完全创建

@Service
public class AServiceImpl implements AService {
    private final ARepository aRepository;
    public AServiceImpl(@Lazy ARepository aRepository) {
        super();
        this.aRepository = aRepository;
    }
    ...
}

来源:

尝试从
ARepositoryCustom
中删除注释
@Repository
,没有必要将
ARepositoryCustom
标记为
@Repository
,因为您希望提供它的实现,而不是使用Spring数据生成它。您有一个扩展的接口
ARepository
ARepositoryCustom
接下来在实现中使用接口
ARepository
。我怀疑SPring Data Jpa是否能够解决问题。另外,我认为该方法属于您的服务,而不属于您的存储库。实际上,@lazy帮助我添加源代码,因为它与
@lazy
@Service
public class AServiceImpl implements AService {
    private final ARepository aRepository;
    public AServiceImpl(@Lazy ARepository aRepository) {
        super();
        this.aRepository = aRepository;
    }
    ...
}