10

根据 Robert C. Martin 的干净代码,方法应该有一个小签名。最好的情况是完全没有参数的方法。相反,建议使用状态变量。这真的很有用。但是无状态会话 bean 呢?

这个名字有点令人困惑,因为 SLSB 可以有状态。你只需要做你的家务,这样你就不会使用上一个 EJB 调用中的状态。

回到干净的代码:我也喜欢在 SLSB 中使用实例变量。这很好用,如果你足够小心,你不会遇到任何状态不一致的问题,因为在每个公共方法调用上都会覆盖状态。

到目前为止,一切都很好。但是如果一个用过的 bean 回到池中会发生什么?它带着它的状态。根据状态的大小,这可能是真正的内存泄漏。JBoss 对 bean 非常慷慨,并且生成了相当多的 bean,从而导致了一些严重的内存消耗——一无所获。

因此,一种方法是在 bean 方法存在并将 bean 返回到池之前清理状态。但在我看来,这似乎是应该避免的无用代码。

有没有合适的方法来处理这个问题?在这种情况下,最佳做法是什么?

4

4 回答 4

1

将实例变量保留在 SLSB 中是完全可能的,因为您不使用代理在方法之间进行调用。例如:

@Stateless 
public class MyEJB {
    private String myVar;

    public void receiveVar(String myVar) {
        this.myVar = myVar;
        useVar();
    }

    private void useVar() {
        // do something with var
    }
}

重点是:当你把这个 SLSB 注入另一个时,任何方法调用都会通过代理来实现实际的 EJB。因此,考虑到在代理实例上调用方法时会从池中检索真实实例,因此不能保证代理在两次或多次调用之间会使用相同的池化实例。所以不可能确保任何声明的类属性的值。

当 SLSB 回到池中时,它会带走每个设置的值(我认为它可能会根据供应商而改变,我不太确定)。但是,池化的 SLSB 实例已经具有先前配置的属性值是完全可能的(并且可以接受)。

我不明白你的意思:

到目前为止,一切都很好。但是如果一个用过的 bean 回到池中会发生什么?它带着它的状态。根据状态的大小,这可能是真正的内存泄漏。JBoss 对 bean 非常慷慨,并且生成了相当多的 bean,从而导致了一些严重的内存消耗——一无所获。

您有任何可以在 SLSB 中使用的“大状态”示例吗?

最后:

我认为处理值的最佳方法始终是处理您将使用的状态变量。使用前设置和使用后清洁。最好的做法是避免这种令人困惑的情况。

希望能帮助到你。

于 2016-06-21T12:31:51.783 回答
0

根据 Robert C. Martin 的干净代码,方法应该有一个小签名。

通常我更喜欢传入(传输对象)作为参数,这样我可以改变我传入的内容而不影响方法签名。

另外,我更喜欢传入一个接口,而不是实际的基类。

public void doSomething(IMyTransferObject arg){
 ...
}

IMyTransferObject接口在哪里

interface IMyTransferObject {
   ...
}

class TransferObject implements IMyTransferObject{
  private String name;
  private String game;
  ... accessor / mutator
}

最好的情况是完全没有参数的方法。相反,建议使用状态变量。这真的很有用。但是无状态会话 bean 呢?

这不能虔诚地遵循,真的没有理由这样做。

于 2012-04-24T14:38:20.073 回答
0

来自http://docs.oracle.com/javaee/6/tutorial/doc/gipjg.html

无状态会话 Bean

无状态会话 bean 不维护与客户端的会话状态。当客户端调用无状态 bean 的方法时,bean 的实例变量可能包含特定于该客户端的状态,但仅限于调用期间。当方法完成时,不应保留特定于客户端的状态。但是,客户端可能会更改池化无状态 bean 中实例变量的状态,并且此状态将保留到池化无状态 bean 的下一次调用。除了在方法调用期间,无状态 bean 的所有实例都是等效的,允许 EJB 容器将实例分配给任何客户端。也就是说,无状态会话 bean 的状态应该适用于所有客户端。

我不是 EE 方面的专家,但在我看来,技术上也允许按照您的计划使用字段。

我假设您必须确保在每次新方法调用时,实例字段都会使用新数据进行更新,并且我认为您应该确保在方法结束后删除引用以确保您不会阻塞旧对象的垃圾收集只是因为它们在仍然保存在某个池中的一些“旧”bean 中被引用。

我会建议这样的模式:

public class MyBean{

  private SomeClass firstObject;
  private SomeOtherClass anotherObject;
  private AndAnotherClass thirdObject;

  public void theMethod(firstObject, anotherObject, thirdObject){
    try {
      this.firstObject = firstObject;
      this.anotherObject = anotherObject;
      this.third = thirdObject;

      startProcessing();

    }finally {
      this.firstObject = null;
      this.anotherObject = null;
      this.third = null;
    }
  }

  private void startProcessing() {
    doStep1();
    doStep2();
    doStep3();
  }

  [...]
}

仍然有很多代码 - 但如果您始终坚持这种风格,您会自动跳过“theMethod”部分并继续阅读“startProcessing”,在那里您拥有干净且没有参数的所有内容。

于 2013-12-10T16:57:34.790 回答
0

保持简单,只需传入参数。即使您可以不这样做,从无状态 EJB 的意图来看,您也不应该这样做。

以零参数为目标的 FWIW 对我来说似乎很愚蠢。瞄准少数,是的,但为了自己的利益而努力为零是愚蠢的。

于 2012-04-24T14:07:30.813 回答