【发布时间】:2015-03-12 08:08:03
【问题描述】:
我的数据模型由三个对象组成,我们称它们为A、B 和C。 A 与 B 和 B 与 C 具有一对多关系。它们仅被建模为接口。
为了获得它们的具体版本,我有接口AProvider、BProvider 和CProvider,它们提供创建、检索和删除操作。
我现在正在通过spring-boot-starter-data-jpa 使用 Spring-JPA 和 Hibernate 进行实现。为此,我有三个@Entitys InternalA、InternalB 和InternalC,它们没有实现A、B 和C 接口,但仅用作传输对象。为了访问它们,我使用 Spring 中自动生成的存储库(请参阅 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 没有区别。
我使用调试器逐步完成了初始化过程,并且确实首先初始化了 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 { ... }
这可行,但我在其他地方读到这是代码异味,应该避免,因为它引入了隐式依赖关系。目前,这对一个模块来说都是本地的,所以在那里没有问题,但后来我的模型会增长,我的模型元素和提供者会分布在多个模块中,所以在王国到来之前我不能使用@DependsOn。
有没有更好的方法来解决这个问题?
【问题讨论】:
标签: java spring spring-boot dependency-injection