具有实例变量的无状态会话 Bean

我有一个无状态会话Bean,其中包含一个公共方法,几个私有方法和一些实例级变量。下面是一个伪代码示例。

private int instanceLevelVar

public void methodA(int x) { 
  this.instanceLevelVar = x;
  methodB();
}

private void methodB() {
  System.out.println(instanceLevelVar);
}

我看到的是,methodB 正在打印未传递到 MethodA 中的值。尽我所能分辨出它正在打印来自同一豆的其他实例的值。这是什么原因造成的?

我应该指出,代码在99.9%的时间内按预期工作。但是,.01%给我带来了一些严重的问题/担忧。

我知道,如果我有不同的公共方法,那么我可能不会在调用之间得到相同的bean,这将导致这种行为。但是,在这种情况下,唯一的调用是对单个公共方法的调用。容器(在本例中为 Glassfish)是否仍会在私有方法调用之间交换 Bean?

(编辑)我将“类级别”重命名为“实例级别”,因为这会引起一些混淆。


答案 1

当我阅读 J2EE 1.4 教程的会话 Bean? 部分时:

无状态会话 Bean

无状态会话 Bean 不维护特定客户端的会话状态。当客户端调用无状态 Bean 的方法时,该 Bean 的实例变量可能包含状态,但仅在调用期间。方法完成后,状态将不再保留。除了在方法调用期间,无状态 Bean 的所有实例都是等效的,允许 EJB 容器将实例分配给任何客户端。

在您的例子中,对 from 的调用将在同一实例上,并且等效于 。因此,我倾向于说,不能输出传递给的值的其他东西。methodB()methodA()this.methodB()methodB()methodA()

EJB 2.0 规范中第 7.11.8 节中的第一句话证实了这一点:“容器必须确保任何时候只有一个线程可以执行实例”。这意味着您不会遇到来自不同客户端(线程)的数据(在实例变量中)将混合出现的情况。在返回之前,您可以确保对实例变量的唯一访问权限!methodA()

也就是说,我并不是说你在某个地方没有问题。但我不认为你的伪代码是等价的。

(编辑:在阅读了对OP问题的一些评论之后,现在显然对使用的伪代码和语义存在疑问。我在下面澄清了可能的后果。

正如Rocket Surgeon所强调的,你所说的类变量到底是什么意思?你真的是指类变量而不是实例变量吗?如果是,伪代码不会反映它,但这显然会导致不可预测的行为。实际上,从 EJB 2.0 规范中的第 24.1.2 节(以及第一点)开始,很明显,您不允许将数据写入类变量(尽管您可以这样做)。这种:)一定有充分的理由。


答案 2

我只是根本不会在无状态会话bean中使用实例变量。无论您遇到问题的原因是什么,这都可能不是您想要做的事情。只需尝试在整个过程中使用局部变量,或者在从无状态会话 Bean 业务方法调用的帮助器类中定义实例变量。


推荐