关于EJB和普通java对象

近期阅读了MasterEjb一书,对于他后来所做的示例有个疑问。简单描述就是:
对于那种只用来存储临时数据并提供一些接口用以操作(set,get)这些数据的对象,我觉得定义成普通的java类不就行了,为什么也要做成EJB呢?
如果说是为了利用容器对EJB对象的复用功能以节约内存的话,那么EJB对象查找管理等的开销是否代价更大呢?

顶顶顶,等待高手。。。

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

EJB里对象的管理是由EJB容器管理的,其中关系到线程,多态,复用等对象在运行应用时所要面对的问题。
如果我们用普通的JavaBean处理数据或相关应用时,我们就要自己写处理这些对象的相关类。而使用了EJB就可以把开发者的精力集中放在他们应该注意的地方上,如数十个表的关联及运算。

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

至于你提到EJB内存管理的话,可以跟你说一个本人使用JBoss的例子。
这是在使用JBoss管理一个(注:只有一个)应用时观察到的。

这个应用用到了10个表,复杂程度算是低了。
JBoss启动后,在没用启动应用时,内存比原来已经用多了60MB。
启动应用后,在启动的瞬间大概跳动了100MB的跳跃,然后回到了20MB左右,之后就再没有波动了。
也就是说系统+应用一共用了80MB左右的内存。

论述得不错。不过似乎没有针对到我的问题,我的意思是:
一个数据结构,比如在C或者C++中就定义成一个struct或者是class。
但是在J2EE下却也被定义成一个EJB(并没有其他一些应用级的需求,如线程,事务等等)。我就是对这种做法感到不太合适!

> 论述得不错。不过似乎没有针对到我的问题,我的意思是:
> 一个数据结构,比如在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而定了)。可是,您一旦写完这些类以后,很多数据交换、提交的处理就不用您去搞了。

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

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


想了一下,觉得很好笑,这个话题如果继续下去的话就会变成
The server side网站上的
Simpler Java - Combatting the complexity of J2EE
的中文版了,呵呵。

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

您可不是第一个...哈哈。
J2EE不是一个必然的选择,这句话,没错,.net也不是王道...哈哈。
可是,除非程序员们能牛的拿出点真东西来,否则...就是吹。

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

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

嗯,又在看了一下,我的确在答非所问。呵呵,不好意思。
等我写一下再回您。本人果然是菜鸟,哈哈。



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
//基本数据
//实现略
}

在上面那个例子里,我特意放了几个不同的内部变量,
有String这个原生类,
Integer这个扩展类,
User这个用户自定义类,
TestLocal 这个EJB 类,
甚至,有int这个不是类的东西。

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

好了,以内存机制来说
TestLocal 由容器分配并释放 //您用了就用了,什么都别管。
这个的话是看复用频率和数据复杂度去决定啦。
//你不用这个对象的话,它不会从内存中消失,等待下次调用。
String,Integer 由gc去管理 //您这是不是对JVM不放心?让他去吧
//你不用这个对象的话,它会从内存中消失,不过不知道什么时候,看gc啦。等待下次调用的话又要创建新实例了。
User 由开发者自己处理 //不好意思,这是您的东西,请自己搞定吧
//生死由您啊,大哥。

int 则在运行中按block的生命期出现并消失。//所属的对象死了就死了,您就别理什么了。
//这....不会用什么内存的,就一格stack而已嘛,别不放心嘛。

假设实现相同功能的两个对象的内存使用,均为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))

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

再回一下,
如果说 用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 啦。

实在很感谢2K兄啊,我比较清楚了。多谢多谢!

我也是菜鸟,越看越晕。。。
汪汪问的是不是为什么要使用值对象的问题?
2k答的是不是EJB为什么比普通class好的问题?