关于EJB和普通java对象

03-12-23 汪汪
近期阅读了MasterEjb一书,对于他后来所做的示例有个疑问。简单描述就是:

对于那种只用来存储临时数据并提供一些接口用以操作(set,get)这些数据的对象,我觉得定义成普通的java类不就行了,为什么也要做成EJB呢?

如果说是为了利用容器对EJB对象的复用功能以节约内存的话,那么EJB对象查找管理等的开销是否代价更大呢?

汪汪
2003-12-24 09:56
顶顶顶,等待高手。。。

wxlin2k
2003-12-24 16:57
高手不回你啦,他们都在那边搞意识形态的斗争。就让我这个小菜鸟来回你一下。

EJB里对象的管理是由EJB容器管理的,其中关系到线程,多态,复用等对象在运行应用时所要面对的问题。

如果我们用普通的JavaBean处理数据或相关应用时,我们就要自己写处理这些对象的相关类。而使用了EJB就可以把开发者的精力集中放在他们应该注意的地方上,如数十个表的关联及运算。

J2EE这一个概念本来就是希望一些企业级的用户(开发者)可以不用考虑这些相对低级的编程(指对于企业级的数据库开发而言,过多的把时间放在这些东西上面会使开发效率下降,以及开发成本上升)

至于你提到EJB内存管理的话,可以跟你说一个本人使用JBoss的例子。

这是在使用JBoss管理一个(注:只有一个)应用时观察到的。

这个应用用到了10个表,复杂程度算是低了。

JBoss启动后,在没用启动应用时,内存比原来已经用多了60MB。

启动应用后,在启动的瞬间大概跳动了100MB的跳跃,然后回到了20MB左右,之后就再没有波动了。

也就是说系统+应用一共用了80MB左右的内存。

汪汪
2003-12-25 11:21
论述得不错。不过似乎没有针对到我的问题,我的意思是:

一个数据结构,比如在C或者C++中就定义成一个struct或者是class。

但是在J2EE下却也被定义成一个EJB(并没有其他一些应用级的需求,如线程,事务等等)。我就是对这种做法感到不太合适!

wxlin2k
2003-12-25 13:52
> 论述得不错。不过似乎没有针对到我的问题,我的意思是:

> 一个数据结构,比如在C或者C++中就定义成一个struct或者是

> lass。

> 但是在J2EE下却也被定义成一个EJB(并没有其他一些应用级?

> 需求,如线程,事务等等)。我就是对这种做法感到不太合适

> ?

其实不然,任何数据类型都有一些应用级的需求,问题是在什么时候而已。

一个数据类型的对象,本身,不能,也不应该包含任何线程或事务的编码,这些东西应该由调用这些对象的应用去思考处理。

数据结构举个例子个人资料

public class Person implemnets Serializable{

private final String name;

private final String gender;

public String getName(){}

public void setName(String newName){}

public String getGender(){}

public void setGender(String newGender){}

public Person(){

}

//其它具体实现略

}

好了,这个Class我们在应用中使用时一般会做为一个数据对象进行操作甚至传送

操作例:

Person me = new Person();

me.setName('XXXX');

String yourname = me.getName();

me = null;

传送

ObjectInputStream in = new ObjectInputStream(request.getInputStream);

Person me = (Person)in.readObject();

ObjectOutputStream out = new ObjectOnputStream(request.getOnputStream);

out.writeObject(me);

注:这些例子都过分地简化了,可能看不出些什么问题。

此外,还有写入数据库等等。在这个例子里,这个抽象的数据类型除了定义以外,还必须由开发者考虑好所有的处理步骤并使用其它类对加以实现。还有一些例子比如,同一个数据结构,如果同时有20人以上去更新完全不同的数据实体,那么你就必须编写相应的处理对象,以便保持这20个实体的数据完整性。而不能写好了这个数据结构就算完事。JAVA、C、C++都是这个道理。

如果EJB的话,EB还是SB,无论是BMP还是CMP,对于开发者,关心的只是这个数据结构本身,是否定义正确,是否逻辑正确等等,关于数据完整性、并行处理这些东西。则交由容器编写者去思考。

如果,您的问题是为什么要按EJB那种格式去编写数据结构?是的,您会觉得这样很别扭,明明很简单的一个数据结构却要写3-5个类(这要看你是写SB、EB、CMP、BMP还有remote还是local而定了)。可是,您一旦写完这些类以后,很多数据交换、提交的处理就不用您去搞了。

那么,我的问题就是,您的应用中,您已经写(处理)好,您的简单数据类型的处理操作了吗?您已经把远程数据传输,调用,数据并发处理,类型内存增减、数据检验、单项多项数据提交回滚的东西都写好了?最重要的是,这些东西可以在多个应用中复用吗?如果以上答案皆是的话,那么,当然是使用简单数据类型去定义数据结构好啦。

希望,这些能回答您的疑问。

wxlin2k
2003-12-25 14:47
想了一下,觉得很好笑,这个话题如果继续下去的话就会变成

The server side网站上的

Simpler Java - Combatting the complexity of J2EE

的中文版了,呵呵。

其实,EJB的特性很多程序员都觉得很别扭,麻烦,多余...等等。

您可不是第一个...哈哈。

J2EE不是一个必然的选择,这句话,没错,.net也不是王道...哈哈。

可是,除非程序员们能牛的拿出点真东西来,否则...就是吹。

starfeng
2003-12-25 14:55
> 您的应用中,您已经写(处理)好,您的简单数据类型的处理操作了吗?您已经把远程数据传输,调用,数据并发处理,类型内存增减、数据检验、单项多项数据提交回滚的东西都写好了?最重要的是,这些东西可以在多个应用中复用吗?如果以上答案皆是的话,那么,当然是使用简单数据类型去定义数据结构好啦

答案是,绝大部份情况下没有

所以绝大部份情况下,你还是用一个class吧。

wxlin2k
2003-12-25 15:09
嗯,又在看了一下,我的确在答非所问。呵呵,不好意思。

等我写一下再回您。本人果然是菜鸟,哈哈。

wxlin2k
2003-12-25 15:32

package myTest;

import java.rmi.*;
import java.sql.*;
import java.util.*;
import javax.ejb.*;
import javax.sql.*;
import myTest.

public class TestBean implements SessionBean {
  private transient TestLocal TestModule; //假想SB
  private String username;//简单对象
  private String password;//简单对象
  private Integer id;//简单JAVA对象
  private transient User user;//简单用户对象
  private int funid//基本数据
  //实现略
}
<p>

在上面那个例子里,我特意放了几个不同的内部变量,

有String这个原生类,

Integer这个扩展类,

User这个用户自定义类,

TestLocal 这个EJB 类,

甚至,有int这个不是类的东西。

我想,这里User就是您说的

>>对于那种只用来存储临时数据并提供一些接口用以操作(set,get)这些数据的对象

好了,以内存机制来说

TestLocal 由容器分配并释放 //您用了就用了,什么都别管。

这个的话是看复用频率和数据复杂度去决定啦。

//你不用这个对象的话,它不会从内存中消失,等待下次调用。

String,Integer 由gc去管理 //您这是不是对JVM不放心?让他去吧

//你不用这个对象的话,它会从内存中消失,不过不知道什么时候,看gc啦。等待下次调用的话又要创建新实例了。

User 由开发者自己处理 //不好意思,这是您的东西,请自己搞定吧

//生死由您啊,大哥。

int 则在运行中按block的生命期出现并消失。//所属的对象死了就死了,您就别理什么了。

//这....不会用什么内存的,就一格stack而已嘛,别不放心嘛。

wxlin2k
2003-12-25 16:30
假设实现相同功能的两个对象的内存使用,均为Test的属性

User = 0.1 MB (一个类)

UserLocal = 0.25MB (4个类)

单个User Instance生成时间0.01秒 (creation of 1 instance)

UserLocal Instance 生成时间 0.05秒(reflection lookup + RMI lookup + creation of 5 instance)

假设有200个并发访问

-------------------------------------

User

Start:

time : User:=0.01 * 200 = 2 sec

ram :User:=0.1 * 200 = 20 MB

After

gc则等待Test清空去清那的20MB

如果有第二次高并发访问...重复以上操作

二次调用数量相等

Start:

time : User:=0.01 * 200 = 2 sec

ram :User:=0.1 * 200 = 20 MB

-------------------------------------

UserLocal

原有Instance 为0

Start:

time : UserLocal =0.05 * 200 = 10 sec

ram :UserLocal =0.25 * 200 = 50 MB

After:

内存不清空,等待下次复用

二次调用数量相等

time: = UserLocal (RMI lookup + reflection lookup )0.01 * 200 = 2 sec

ram....no change

------------------------------------------------

二次调用数量不等 300

Start:

time : User:=0.01 * 300 = 3 sec

ram :User:=0.1 * 300 = 增加 30 MB

二次调用数量不等 300

Start:

time : 200*(rmi + reflection lookup time) + 100 * creation time = unknow 可能是 4-5秒左右

ram :UserLocal =0.25 * 100 = 增加 25MB

-------------------------------------------------

也就是说EJB希望通过优化多次使用中的权差来达到系统的高效并发反应速度。而用普通class的话,则没有了相应的系统优化机制,完全依赖程序员本身的代码优化。

他们的性能变化为

User = n+ n1+ n2+ n3 + .....nm

UserLocal = n + (n1-n) + (n2-n1) + (n3 -n2) +....(nm- n(m-1))

用User的话,性能比较死板来多少,每次的效率都是O(n)

用UserLocal的话,效率是O(delta(n))

这样的解释,您觉得如何?

wxlin2k
2003-12-26 16:39
再回一下,

如果说 用EJB的话

TestLocal{

private houseLocal[n]

}

houseLocal{

priave userLocal[m]

}

如果说 用普通对象的话

Test{

private house[n]

}

HomeLocal{

priave user[m]

}

创建时

那么普通对象就会跳跃 X * n * m 个内存位,

EJB就会只用就会跳跃X (因为n 和 m个内部EJB都已经在内存里了) 个内存位。

这样的话,不就是更省内存嘛。所以咯,当然是用EJB不用普通Class 啦。

汪汪
2003-12-29 11:24
实在很感谢2K兄啊,我比较清楚了。多谢多谢!

missxkl
2003-12-29 11:42
我也是菜鸟,越看越晕。。。

汪汪问的是不是为什么要使用值对象的问题?

2k答的是不是EJB为什么比普通class好的问题?

猜你喜欢