清理代码,无状态会话bean和私有状态

时间:2012-04-24 14:03:36

标签: java coding-style ejb-3.0 java-ee-6 ejb-3.1

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

这个名字有点令人困惑,因为SLSB可以拥有州。您只需要进行内务管理,这样就不会使用先前EJB调用中的状态。

回到清洁代码:我也喜欢在SLSB中使用实例变量。这样可以正常工作,如果你足够小心,你就不会遇到状态不一致的问题,因为每次公共方法调用都会覆盖状态。

到目前为止一切顺利。但是如果用过的bean回到池中会发生什么?它采取了它的状态。根据状态的大小,这可能是真正的内存泄漏。 JBoss非常慷慨地使用bean,它们产生了大量的内存,导致一些严重的内存消耗 - 无所不能。

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

有没有正确的方法来解决这个问题?在这种情况下,最佳做法是什么?

4 个答案:

答案 0 :(得分:0)

让生活变得简单,只需输入参数即可。即使你可以做其他事情,显然从无状态EJB的意图来看,你不应该

FWIW旨在实现零参数的目标对我来说似乎很愚蠢。瞄准少数,是的,但为了自己的利益而争取零只是愚蠢。

答案 1 :(得分: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呢?

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

答案 2 :(得分:0)

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

  

无国籍会话豆

     

无状态会话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”,在那里你可以干净利落地拥有所有东西。

答案 3 :(得分:0)

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

@Stateless 
public class MyEJB {
    private String var;

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

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

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

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

我在这里没有理解你的观点:

  

到目前为止一切顺利。但是如果用过的bean回到池中会发生什么?   它采取了它的状态。这取决于州的大小   可能是真正的内存泄漏。 JBoss对豆类非常慷慨   产生了很多它们导致一些严重的记忆   消费 - 无所事事。

你有什么例子"大州"你可以拥有SLSB吗?

最后:

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

希望它有所帮助。