Java SpringJPA:如何通过注入获得正确的依赖关系?

Java SpringJPA:如何通过注入获得正确的依赖关系?,java,spring,spring-boot,dependency-injection,Java,Spring,Spring Boot,Dependency Injection,我的数据模型由三个对象组成,我们称它们为A,B和CA与B有一对多关系,而B与C有一对多关系。它们仅作为接口建模 为了获得它们的具体版本,我有接口AProvider、BProvider和CProvider,它们提供创建、检索和删除操作 我现在正在通过springbootstarterdatajpa使用springjpa和Hibernate实现。为此,我有三个@实体sInternalA、InternalB和InternalC,它们不实现A、B和C接口,但仅用作传输对象。为了访问它们,我使用Sprin

我的数据模型由三个对象组成,我们称它们为
A
B
C
<代码>A与
B
有一对多关系,而
B
C
有一对多关系。它们仅作为接口建模

为了获得它们的具体版本,我有接口
AProvider
BProvider
CProvider
,它们提供创建、检索和删除操作

我现在正在通过
springbootstarterdatajpa
使用springjpa和Hibernate实现。为此,我有三个
@实体
s
InternalA
InternalB
InternalC
,它们不实现
A
B
C
接口,但仅用作传输对象。为了访问它们,我使用Spring自动生成的存储库(请参见
crudepository

为了创建“真实”对象,我有
XProvider
接口的实现,这些接口注入了必要的依赖关系。此结构如下(我更喜欢
javax.inject
style injection):

我发现这应该是可行的,
AutowireCapableBeanFactory
正确地确定了首先实例化什么。但这仅适用于
BProviderImpl
,例如,在移除
CProviderImpl
时。只要
CProviderImpl
存在,初始化就会失败,
找不到[com.somewhere.BProvider]类型的合格bean

如果我使用
@Autowired
而不是
@Inject
则没有区别

我使用调试器逐步完成了初始化过程,
CProvider
确实是首先初始化的,也就是说,bean工厂没有正确地判断出它需要
BProvider
,而后者又需要
AProvider

我当前的解决方法是使用
@DependsOn
如下:

@Component("myAProvider")
public class AProviderImpl implements AProvider { ... }

@Component("myBProvider")
@DependsOn("myAProvider")
public class BProviderImpl implements BProvider { ... }

@Component("myCProvider")
@DependsOn("myBProvider")
public class CProviderImpl implements CProvider { ... }
这是可行的,但我在别处读到,这是一种代码味道,应该避免,因为它引入了隐式依赖。目前,这都是一个模块的本地版本,因此在那里没有问题,但稍后我的模型将增长,并且我的模型元素和提供程序将分布在多个模块上,因此在kingdom到来之前,我无法使用
@DependsOn


有更好的方法解决这个问题吗?

您可以使用
@Order
注释,这将使Bean加载具有优先级,并且不会像
@DependsOn
那样污染加载层次结构。有了这一点,以后您当然可以毫无问题地将设计模块化。最低顺序值具有最高优先级

@Component("myAProvider")
@Order(1)
public class AProviderImpl implements AProvider { ... }

@Component("myBProvider")
@Order(2)
public class BProviderImpl implements BProvider { ... }

@Component("myCProvider")
@Order(3)
public class CProviderImpl implements CProvider { ... }

我发现了另一种解决方法:延迟初始化。由于我的
XProvider
s的初始化不是长时间运行的,所以我只添加了
@Lazy
注释。通过这种方式,Spring创建未初始化的实例并将它们添加到注册表中,当稍后访问注入的依赖项时,它将被初始化


我不知道这是否是最好的解决方案,但我认为它比使用
@DependsOn
要好,而且它应该在模块边界上工作。

我只是尝试了一下,但没有工作。我得到了“没有符合条件的bean”例外。我发现使用
@Lazy
似乎可以达到目的。这样,bean按照bean工厂认为它必须使用的顺序进行初始化,但是所有注入的内容在第一次需要时就被初始化。
@Component("myAProvider")
@Order(1)
public class AProviderImpl implements AProvider { ... }

@Component("myBProvider")
@Order(2)
public class BProviderImpl implements BProvider { ... }

@Component("myCProvider")
@Order(3)
public class CProviderImpl implements CProvider { ... }