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 类型。
因此,您观察到的行为符合规范。
我已经解决了将 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
只是 EJBSomeClass
的一个 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 类型。
因此,您观察到的行为符合规范。