Spring JPA:如何通过注入获得依赖性?

时间:2015-03-12 08:08:04

标签: java spring spring-boot dependency-injection

我的数据模型由三个对象组成,我们称之为ABCAB以及BC之间存在一对多的关系。它们仅被建模为接口。

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

我现在通过spring-boot-starter-data-jpa使用Spring-JPA和Hibernate进行实现。为此,我有三个@Entity s InternalAInternalBInternalC未实现AB和{{1} } interfaces,但仅用作传输对象。要访问它们,我使用Spring自动生成的存储库(参见C)。

创建"真实"对象,我有CrudRepository接口的实现,它们注入了必要的依赖项。这个结构如下(我更喜欢XProvider样式注入):

javax.inject

我发现这应该有效,而@Component public class AProviderImpl implements AProvider { @Inject private InternalARepository _aRepository; // implementation } @Component public class BProviderImpl implements BProvider { @Inject private InternalBRepository _bRepository; @Inject private AProvider _aProvider; // implementation } @Component public class CProviderImpl implements CProvider { @Inject private InternalCRepository _cRepository; @Inject private BProvider _bProvider; // implementation } 正确地找出了首先要实例化的内容。但这仅适用于AutowireCapableBeanFactory,例如,在删除BProviderImpl时。只要CProviderImpl存在,初始化就会失败并显示CProviderImpl

如果我使用No qualifying bean of type [com.somewhere.BProvider] found代替@Autowired,则没有任何区别。

我使用调试器逐步完成初始化过程,@Inject确实首先被初始化,即bean工厂没有正确地确定它需要CProvider,而BProvider又需要AProvider 1}}首先。

我目前的解决方法是使用@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 { ... }

这有效,但我在别处读到这是代码味道,应该避免,因为它引入了隐式依赖。目前,这对于一个模块来说都是本地的,所以它没有问题,但是后来我的模型会增长,我会将模型元素和提供者分布在多个模块上,所以在王国到来之前我不能使用@DependsOn。 / p>

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

2 个答案:

答案 0 :(得分:0)

您可以使用@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 { ... }

答案 1 :(得分:0)

我找到了另一种解决方法:延迟初始化。由于XProvider的初始化时间不长,我只是添加了@Lazy注释。这样,Spring创建了未初始化的实例并将它们添加到注册表中,并且稍后在访问注入的依赖项时,它将被初始化。

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