注入静态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规范和app客户端容器 )。

为什么会这样? 首先, EJB中完全禁止读/写静态字段 (这是EJB限制的一部分)。 从为什么我不能在我的企业bean中使用非最终静态字段?

EJB中不允许使用非最终静态类字段,因为这些字段使企业bean难以或无法分发 。 静态类字段在特定类的所有实例之间共享,但仅在单个Java虚拟机(JVM)中共享。 更新静态类字段意味着在类的所有实例之间共享字段值的意图。 但是,如果一个类同时在多个JVM中运行,则只有与更新实例在同一JVM中运行的那些实例才能访问新值。 换句话说,如果在单个JVM中运行,非最终静态类字段的行为将不同于在多个JVM中运行的行为。 EJB容器保留了跨多个JVM(在同一服务器或任何服务器集群上运行)分发企业bean的选项。 不允许使用非最终静态类字段,因为企业bean实例的行为会有所不同,具体取决于它们是否是分布式的。

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

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

所以最后,是的,这是胡说八道。

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

因为规范不允许它:

5.2.3注释和注射

如以下部分所述,可以注释某些容器管理的组件类的字段或方法,以请求将来自应用程序组件的环境的条目注入到类中。 […] 对于除应用程序客户机主类之外的所有类,字段或方法不得为静态。

请注意,exception(应用程序客户机主类)仅存在,因为这些类从未实例化。 基本上,静态字段通常是有问题的,并且在应用程序服务器中是双重的,因为它们可以绕过请求处理线程和事务的分离,这是首先使用应用程序服务器的全部要点。

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

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