注入静态EJB,废话?

问题描述:

我想写这一段代码:注入静态EJB,废话?

@Stateless 
public class MyEjb 
{ 
    @EJB 
    private static MyOtherEjbWhichIWantStatic myOtherEjb; 
} 

这对我来说很有意义,我想注入一个EJB在我的课,作为静态元素,由于种种原因。

Java不是很满意,不幸的是

com.sun.enterprise.container.common.spi.util.InjectionException: Illegal use of static field private static MyOtherEjbWhichIWantStatic myOtherEjb on class that only supports instance-based injection 

我不明白,为什么我不能注入静态EJB到另一个EJB?

正如其他人所指出的,这是不规范允许和短版就是@EJB注释仅支持静态成员的班级,main()功能(参见EJB 3.0规范和应用程序客户端容器)。

为什么会这样呢?首先,读写静态字段在EJB中是完全禁止的(这是EJB限制的一部分)。从Why can't I use nonfinal static fields in my enterprise bean?

非最终静态类字段中的EJB不允许的,因为这些领域使企业Bean很难或不可能分发。静态类字段在特定类的所有实例*享,但仅在单个Java虚拟机(JVM)*享。更新静态类字段意味着要在该类的所有实例之间共享该字段的值。但是,如果一个类同时在多个JVM中运行,那么只有那些与更新实例在同一个JVM中运行的实例才能访问新值。换句话说,如果在单个JVM中运行,非最终静态类字段的行为将会不同,而不是在多个JVM中运行。 EJB容器保留了跨多个JVM(运行在同一台服务器上或任何一个服务器集群上)分发企业bean的选项。非最终的静态类字段是不允许的,因为企业bean实例将根据它们是否被分发而表现不同。

如果这些字段标记为final,则使用静态类字段是可以接受的做法。由于最终字段无法更新,因此企业bean的实例可以由容器分发,而不用担心这些字段的值会变得不同步。

但是,虽然使用只读静态字段是允许的,但这不适用于EJB。无状态EJB可能会被合并,容器可能会决定销毁它们(这是特定于实现的),并且您想让容器选择要使用的实例,尤其是在分布式环境中。换句话说,永远不要假设你被绑定到一个特定的实例。

所以最后,是的,这是一个废话。

+0

晶莹剔透,谢谢! – 2010-07-07 15:21:31

从Java EE 5规范注入静态EJB只允许在应用程序客户端主类中使用。

对于除应用程序客户端主类以外的所有类,字段或方法不能是静态的。由于应用程序客户端使用与J2SE应用程序相同的生命周期,因此应用程序客户端容器不会创建应用程序客户端主类的任何实例。相反,调用静态main方法。为了支持应用程序客户端主类的注入,为注入注释的字段或方法必须是静态的。

我不明白,为什么我不能注入 静态EJB到另一个EJB?

由于the spec不允许它:

5.2.3Annotations和注射

如以下 段,某些 容器管理组件类的字段或方法描述 可能被注释为要求从应用程序组件的 环境中注入一个 条目int o 班。 [...] 对于除 应用程序客户端主类之外的所有类, 字段或方法不得为 静态。

请注意,异常(应用程序客户端主类)只存在,因为这些类永远不会实例化。基本上,静态字段通常是有问题的,而且在应用程序服务器中也是如此,因为它们可以绕开请求处理线程和事务的分离,这是首先使用应用程序服务器的关键。