java 注入静态 EJB,胡说八道?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3195365/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 00:45:50  来源:igfitidea点击:

Injecting a static EJB, nonsense?

javastaticdependency-injectionannotationsejb-3.0

提问by Cyril Gandon

I want to write this piece of code :

我想写这段代码:

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

It makes sense to me, that I want to inject an EJB in my class, as a static element, for various reason.

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

Java is not very happy with that unfortunately

不幸的是,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

I don't get it, why can't I inject a static EJB into another EJB ?

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

回答by Pascal Thivent

As others pointed out, this is not allowed by the specification, and the short version is that the @EJBannotation is only supported for static members in classes with a main()function (see the EJB 3.0 specification and the app client container).

正如其他人指出的那样,规范不允许这样做,简短的版本是@EJB注释仅支持具有main()函数的类中的静态成员(请参阅 EJB 3.0 规范和应用程序客户端容器)。

Why is it so? First of all, read/write static fields are totally forbidden in EJBs(this is part of the EJB restriction). From Why can't I use nonfinal static fields in my enterprise bean?

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

Nonfinal static class fields are disallowed in EJBs because such fields make an enterprise bean difficult or impossible to distribute. Static class fields are shared among all instances of a particular class, but only within a single Java Virtual Machine (JVM). Updating a static class field implies an intent to share the field's value among all instances of the class. But if a class is running in several JVMs simultaneously, only those instances running in the same JVM as the updating instance will have access to the new value. In other words, a nonfinal static class field will behave differently if running in a single JVM, than it will running in multiple JVMs. The EJB container reserves the option of distributing enterprise beans across multiple JVMs (running on the same server, or on any of a cluster of servers). Nonfinal static class fields are disallowed because enterprise bean instances will behave differently depending on whether or not they are distributed.

It is acceptable practice to use static class fields if those fields are marked as final. Since final fields cannot be updated, instances of the enterprise bean can be distributed by the container without concern for those fields' values becoming unsynchronized.

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

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

But while using read-only static fields is allowed, this wouldn't be appropriate for EJBs. Stateless EJBs may be pooled, a container may decide to destroy them (this is implementation specific) and you want to let the container choose which instance you're going to use, especially in distributed environments. In other words, never assume you are tied to a particular instance.

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

So at the end, yes, this is a nonsense.

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

回答by Michael Borgwardt

I don't get it, why can't I inject a static EJB into another EJB ?

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

Because the specdoes not allow it:

因为规范不允许:

5.2.3Annotations and Injection

As described in the following sections, a field or method of certain container-managed component classes may be annotated to request that an entry from the application component's environment be injected into the class. [...] For all classes except application client main classes, the fields or methods must not be static.

5.2.3注解与注入

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

Note that the exception (application client main classes) only exists because those classes are never instantiated. Basically, static fields are generally problematic, and doubly so in an application server, because they can circumvent the separation of request handling threads and transactions, which are the whole point of using an application server in the first place.

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

回答by Robby Pond

From Java EE 5 specification injection of static EJBs is only allowed in application client main classes.

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

For all classes except application client main classes, the fields or methods must not be static. Because application clients use the same lifecycle as J2SE applications, no instance of the application client main class is created by the application client container. Instead, the static main method is invoked. To support injection for the application client main class, the fields or methods annotated for injection must be static.

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