java 是否有可能在定义CDI生产者的模块中隔离它们(在具有共享模块的模块应用程序中)

xzlaal3s  于 2023-05-27  发布在  Java
关注(0)|答案(1)|浏览(153)

设置

假设您有两个bean归档模块A和B,其中A依赖于B(我们不能修改B)。在B中,假设有一个类,其中注入了EntityManager,如下所示:

@Dependent
class SomeClassImpl implements SomeClass {
    private EntityManager em;
    
    public SomeClassImpl() {}

    @Inject
    public SomeClassImpl(EntityManager em) {
        this.em = em;
    }
    
    ...

}
  • 请注意,SomeClass接口从不直接注入A。也就是说,SomeClassSomeRepository的依赖项,而SomeRepository又是SomeUseCase的依赖项,这就是注入A的内容。

因为实体管理器不是一个cdibean,所以我们可以在A中定义它的生产者在WAR归档中部署时,这将按照预期工作。

问题

现在,考虑以下情况:你有三个bean归档模块X、Y和Z,其中X和Y都依赖于Z,如上所定义。因为X和Y为EntityManager定义了一个生产者(X和Y不同),并且这些生产者对所有模块都是可见的,所以我们必须向X和Y的生产者添加限定符以避免不满足的依赖异常。

现在,问题是我们如何处理Z中的模糊性?

如果生产者只对定义的模块可见,那么这将减少第一个场景。但是因为它们不是,所以我们将得到org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type EntityManager with qualifiers
注意:虽然这可以通过自定义作用域来解决,但如果可能的话,我希望现在避免构建一个。
如果是你,你会如何着手解决这个问题?

lkaoscv7

lkaoscv71#

由于您有两个相同类型的bean(两个EntityManagers),因此必须使用限定符来区分它们。但是如何定义EntityManager的2个合格示例中的哪一个被注入到SomeClassImpl中呢?
幸运的是,SomeClassImpl使用构造函数注入,因此您可以自己构造它。我建议使用两个生产者方法(可以在同一个bean中),每个方法都提供一个手工构造的、限定的SomeClassImpl示例;假设@Q1@Q2是限定符2个不同的EntityManager也由@Q1@Q2限定:

@Q1
@Dependent
@Produces
public SomeClassImpl(@Q1 EntityManager em) {
    return new SomeClassImpl(em);
}

@Q2
@Dependent
@Produces
public SomeClassImpl(@Q2 EntityManager em) {
    return new SomeClassImpl(em);
}

CDI仍然会找到一个不合格的SomeClassImpl示例,并且可能会抱怨不明确的依赖关系。如果是这样,我将尝试使用beans.xml<scan><exclude>元素)的排除机制从bean发现中排除不合格的SomeClassImpl

相关问题