CDI 1.2 (WildFly 8.2),javax.enterprise.inject.Instance<SomeIFace> 不获取不直接实现 SomeIFace 的 beans

CDI 1.2 (WildFly 8.2), javax.enterprise.inject.Instance<SomeIFace> does not get beans which do not implement SomeIFace directly

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

public interface SomeIFace {

    void doStuff();
}

然后有一个摘要class采用SomeIFace如下:

public abstract class SomeAClass implements SomeIFace {

    @Resource
    private TimerService ts;

    public TimerService getTimerService() {
        return ts;
    }

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

托管 bean 的实际实现扩展了抽象 class SomeAClass,如下所示:

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

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

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

@Inject
@Any
private Instance<SomeIFace> beans;

问题是 beans 是空的!

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

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

提前致谢!

智日

更新:

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

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

3.1.2: The unrestricted set of bean types for a managed bean contains the bean class, every superclass and all interfaces it implements directly or indirectly. (...) 3.2.2: The unrestricted set of bean types for a session bean contains all local interfaces of the bean and their superinterfaces. If the session bean has a no-interface view, the unrestricted set of bean types contains the bean class and all superclasses. (...)

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

  • 对于托管(非 EJB)bean,规范明确指出 "all directly or indirectly" 实现的接口是 bean 的一种 bean 类型。对我来说,这意味着 SomeIFace(由 [=11= 实现],由 SomeClass 扩展)将是 SomeClass 的 bean 类型,如果 SomeClass是一个托管(非 EJB)bean。
  • 对于会话 (EJB) bean,规范在我看来有点模糊。然而,对我来说,"all local interfaces of the bean" 读起来就像接口 SomeIFace 只是 EJB SomeClass 的一个 bean 类型,如果 SomeClass 直接实现它(而不是它只扩展 SomeAClass 反过来,实现 SomeIFace).
  • 但还要注意,如果您将 SomeIFace 直接添加到 SomeClass,则 bean 不能 通过 @Inject SomeClass 注入!这是因为只有 "the session bean has no-interface view",bean class 本身是一个 bean 类型——否则,只有 "all local interfaces of the bean and their superinterfaces"(和 java.lang.Object)是 bean 类型。

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