我的数据模型由三个对象组成,我们称之为A
,B
和C
。 A
与B
以及B
与C
之间存在一对多的关系。它们仅被建模为接口。
为了获得它们的具体版本,我有接口AProvider
,BProvider
和CProvider
,它们提供创建,检索和删除操作。
我现在通过spring-boot-starter-data-jpa
使用Spring-JPA和Hibernate进行实现。为此,我有三个@Entity
s InternalA
,InternalB
和InternalC
未实现A
,B
和{{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>
有没有更好的方法来解决这个问题?
答案 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
要好,而且它应该在模块边界上工作。