【问题标题】:CDI 1.2 (WildFly 8.2), javax.enterprise.inject.Instance<SomeIFace> does not get beans which do not implement SomeIFace directlyCDI 1.2 (WildFly 8.2),javax.enterprise.inject.Instance<SomeIFace> 没有得到不直接实现 SomeIFace 的 bean
【发布时间】:2015-09-13 14:05:25
【问题描述】:

我已经在解决将 bean 实现注入 javax.enterprise.inject.Instance&lt;SomeIFace&gt; 的问题了。我有几个 bean (EJB Singletons),它们扩展了一个实现 SomeIFace 的抽象类 - 请参见下面的场景。

public interface SomeIFace {

    void doStuff();
}

那么就有一个采用SomeIFace的抽象类如下:

public abstract class SomeAClass implements SomeIFace {

    @Resource
    private TimerService ts;

    public TimerService getTimerService() {
        return ts;
    }

    @Timeout
    public void timeout() {
        doStuff();
    }
}

托管bean的实际实现扩展抽象类SomeAClass如下:

@Singleton
@Startup
@TransactionManagement(TransactionManagementType.BEAN)
public class SomeClass extends SomeAClass {

    /**
     * {@inheritDoc}
     */
    @Override
    public void doStuff() {
        ...
    }
}

然后在另一个类中,我想获取对所有实现SomeIFace 的托管 bean 的引用,即:

@Inject
@Any
private Instance<SomeIFace> beans;

问题是beans 是空的!

当我再次将SomeIFace 显式添加到实现bean 类(即public class SomeClass extends SomeAClass implements SomeIFace)时,beans 不为空并出现引用。

有谁能解释一下,为什么我需要在 bean 实现上直接重复 SomeIFace 接口以使 CDI 1.2 正常工作?在以前版本的 CDI 中,它工作正常。

提前谢谢你!

吉日

更新:

这个奇怪的注入问题只发生在 EJB Singletons (@javax.ejb.Singleton) 的 bean 上。当 bean 使用 @javax.inject.Singleton@javax.enterprise.context.ApplicationScoped 注释时,不需要重复接口声明,并且可以发现 bean。但是,TimerService 不能注入到非 EJB bean 中

【问题讨论】:

  • 嗯听起来不太对劲。所有这些都在同一个WAR中吗?这里涉及到任何 JAR 文件吗?
  • 是的,都在同一个WAR中,实际上在同一个JAR文件中
  • 它也发生在 Glassfish,并且发生在任何 EJB(单音或无状态)上,在我的测试期间我能够注入 Instance bean,但是一旦我引入一个接口来定义一个本地查看,该 bean 不再出现在 bean 列表中 @Inject Instance beans。解决此问题的一种方法是直接使用接口显式标记 EJB 实现。

标签: jakarta-ee dependency-injection ejb cdi wildfly


【解决方案1】:

似乎新行为与CDI 1.2 Spec 中指定的一样:

3.1.2:托管 bean 的不受限制的 bean 类型集包含 bean 类、每个超类以及它直接或间接实现的所有接口。 (...) 3.2.2:会话 bean 的不受限制的 bean 类型集包含 bean 的所有本地接口及其超接口。如果会话 bean 具有无接口视图,则不受限制的 bean 类型集包含 bean 类和所有超类。 (...)

注意托管 bean 和会话 bean 的 bean 类型定义的区别。

  • 对于托管(非 EJB)bean,规范明确指出“所有直接或间接”实现的接口都是 bean 的 bean 类型。对我来说,这意味着SomeIFace(由SomeAClass 实现,由SomeClass 扩展)将是SomeClass 的bean 类型,如果SomeClass 是托管(非EJB)bean。
  • 对于会话 (EJB) bean,规范在我看来有点模糊。但是,对我来说,“bean 的所有本地接口”读起来就像接口 SomeIFace 只是 EJB SomeClass 的 bean 类型,如果 SomeClass 直接实现它(而不是它只扩展 SomeAClass , 进而实现SomeIFace)。
  • 但还要注意,如果您将SomeIFace 直接添加到SomeClass,则bean 不能 再通过@Inject SomeClass 注入!这仅当“会话 bean 具有无接口视图”时,bean 类本身是 bean 类型——否则,只有“bean 的所有本地接口及其超接口”(和java.lang.Object)是 bean 类型。

因此,您观察到的行为符合规范。

【讨论】:

    猜你喜欢
    • 2017-10-19
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    • 2013-03-02
    • 1970-01-01
    • 2021-11-06
    • 2020-03-17
    相关资源
    最近更新 更多