鹰翔宇空
学习和生活
BlogJava
首页
新随笔
联系
聚合
管理
110 Posts :: 141 Stories :: 315 Comments :: 1 Trackbacks
公告
欢迎和大家成为朋友!
欢迎和大家就任何技术进行交流!
QQ:77542728
MSN:hnlyhyq@hotmail.com
Email:hnlyhyq@163.com
常用链接
我的随笔
我的评论
我的参与
最新评论
留言簿
(16)
给我留言
查看公开留言
查看私人留言
随笔分类
(107)
休闲娱乐(4)
学习体会(40)
工作之余(7)
心情驿站(15)
技术文摘(41)
生活百科
随笔档案
(109)
2013年1月 (1)
2009年4月 (1)
2008年7月 (1)
2008年6月 (2)
2008年4月 (1)
2008年3月 (3)
2007年9月 (3)
2007年6月 (1)
2006年11月 (7)
2006年10月 (1)
2006年9月 (3)
2006年8月 (1)
2006年7月 (2)
2006年5月 (10)
2006年4月 (12)
2006年3月 (15)
2006年2月 (24)
2006年1月 (12)
2005年12月 (6)
2005年11月 (3)
文章分类
(145)
AJAX(4)
datebase(29)
EJB(4)
hibernate(13)
IDE(5)
java(35)
javascript(4)
jboss_seam
opensource(7)
Spring(3)
web(20)
webwork
工作之余(1)
技术文摘(20)
生活感悟
文章档案
(141)
2007年2月 (4)
2006年9月 (1)
2006年8月 (1)
2006年7月 (4)
2006年6月 (7)
2006年5月 (31)
2006年4月 (7)
2006年3月 (2)
2006年2月 (60)
2006年1月 (24)
收藏夹
(22)
AJAX(8)
java(7)
javascript
JDBC(4)
web(1)
开源项目(2)
java
javascript
jdbc
neweagle的Blog
主要是数据库方面的一些知识
web
其它
开源项目
ant简单应用
关于ant简单应用的
我的好友
lizongbo(蝙蝠太极)
lizongbo的BLOG
张智辉
最新随笔
1. Linux上安装MQ7.5
2. Oracle to buy sun
3. ORACLE查询表方法
4. 本地化(国际化)rich:calendar控件
5. 使用Richface通过js脚本直接局部刷新
6. jboss seam 常用控件
7. jboss seam 组件驱动的事件
8. 多线程-synchronized
9. jboss_seam初学入门建议
10. 如何使用java动态创建ODBC数据源
搜索
最新评论
1. re: 使用javamail发信过程中的一些问题及解决方法
@痞子z
大哥求解,
--手动阀
2. re: 使用javamail发信过程中的一些问题及解决方法
刚做了一个 发送企业邮箱的,有什么不明白的可以咨询我:qq 775048682,欢迎大家交流
--林仔youyou
3. re: 使用javamail发信过程中的一些问题及解决方法
评论内容较长,点击标题查看
--林仔youyou
4. re: 用java调用oracle存储过程总结
学习了
--bean先森
5. re: 用java调用oracle存储过程总结
SB一个 不解释@ice
--iversion
阅读排行榜
1. 用java调用oracle存储过程总结(86482)
2. 使用javamail发信过程中的一些问题及解决方法(75344)
3. MySql常用命令总结(12374)
4. java中数值计算的精度问题(10501)
5. 如何避免不小心关掉web浏览器窗口(7066)
评论排行榜
1. 用java调用oracle存储过程总结(100)
2. 使用javamail发信过程中的一些问题及解决方法(36)
3. 使用Richface通过js脚本直接局部刷新(11)
4. 项目开发成功与失败的关键影响因素----时间篇(11)
5. java中数值计算的精度问题(9)
《EJB调用的原理分析》
引自:
http://forum.javaeye.com/viewtopic.php?t=1036
一个远程对象至少要包括4个class文件:远程对象;远程对象的接口;实现远程接口的对象的stub;对象的skeleton这4个class文件。
在EJB中则至少要包括10个class:
Bean类,特定App Server的Bean实现类
Bean的remote接口,特定App Server的remote接口实现类,特定App Server的remote接口的实现类的stub类和skeleton类
Bean的home接口,特定App Server的home接口实现类,特定App Server的home接口的实现类的stub类和skeleton类
和RMI不同的是,EJB中这10个class真正需要用户编写的只有3个,分别是Bean类和它的remote接口,home接口,至于其它的7个class到底是怎么生成,被打包在什么地方,或者是否需要更多的类文件,会根据不同的App Server表现出比较大的差异,不能一概而论。
拿我最熟悉的Weblogic的来说吧,Weblogic的Bean实现类,以及两个接口的Weblogic的实现类是在ejbc的时候被打包到EJB的jar包里面的,这3个class文件可以看到。而home接口和remote接口的Weblogic的实现类的stub类和skeleton类是在EJB被部署到Weblogic的时候,由Weblogic动态生成stub类和Skeleton类的字节码,因此看不到这4个类文件。
对于一次客户端远程调用EJB,要经过两个远程对象的多次RMI循环。首先是通过JNDI查找Home接口,获得Home接口的实现类,这个过程其实相当复杂,首先是找到Home接口的Weblogic实现类,然后创建一个Home接口的Weblogic实现类的stub类的对象实例,将它序列化传送给客户端(注意stub类的实例是在第1次RMI循环中,由服务器动态发送给客户端的,因此不需要客户端保存Home接口的Weblogic实现类的stub类),最后客户端获得该stub类的对象实例(普通的RMI需要在客户端保存stub类,而EJB不需要,因为服务器会把stub类的对象实例发送给客户端)。
客户端拿到服务器给它的Home接口的Weblogic实现类的stub类对象实例以后,调用stub类的create方法,(在代码上就是home.create(),但是后台要做很多事情),于是经过第2次RMI循环,在服务器端,Home接口的Weblogic实现类的skeleton类收到stub类的调用信息后,由它再去调用Home接口的Weblogic实现类的create方法。
在服务端,Home接口的Weblogic实现类的create方法再去调用Bean类的Weblogic实现类的ejbCreate方法,在服务端创建或者分配一个EJB实例,然后将这个EJB实例的远程接口的Weblogic实现类的stub类对象实例序列化发送给客户端。
客户端收到remote接口的Weblogic实现类的stub类的对象实例,对该对象实例的方法调用(在客户端代码中实际上就是对remote接口的调用),将传送给服务器端remote接口的Weblogic实现类的skeleton类对象,而skeleton类对象再调用相应的remote接口的Weblogic实现类,然后remote接口的Weblogic实现类再去调用Bean类的Weblogic实现类,如此就完成一次EJB对象的远程调用。
看了一遍帖子,感觉还是没有说太清楚,既然写了帖子,就想彻底把它说清楚。
先拿普通RMI来说,有4个class,分别是远程对象,对象的接口,对象的stub类和skeleton类。而对象本身和对象的stub类同时都实现了接口类。而我们在客户端代码调用远程对象的时候,虽然在代码中操纵接口,实质上是在操纵stub类,例如:
接口类:Hello
远程对象:Hello_Server
stub类:Hello_Stub
skeleton类:Hello_Skeleton
客户端代码要这样写:
Hello h = new Hello_Stub();
h.getString();
我们不会这些写:
Hello_Stub h = new Hello_Stub();
h.getString();
因为使用接口适用性更广,就算更换了接口实现类,也不需要更改代码。因此客户端需要Hello.class和Hello_Stub.class这两个文件。但是对于EJB来说,就不需要Hello_Stub.class,因为服务器会发送给它,但是Hello.class文件客户端是省不了的,必须有。表面上我们的客户端代码在操纵Hello,但别忘记了Hello只是一个接口,抽象的,实质上是在操纵Hello_Stub。
拿Weblogic上的EJB举例子,10个class分别是:
Bean类:HelloBean (用户编写)
Bean类的Weblogic实现类:HelloBean_Impl (EJBC生成)
Home接口:HelloHome (用户编写)
Home接口的Weblogic实现类 HelloBean_HomeImpl(EJBC生成)
Home接口的Weblogic实现类的stub类 HelloBean_HomeImpl_WLStub(部署的时候动态生成字节码)
Home接口的Weblogic实现类的skeleton类 HelloBean_HomeImpl_WLSkeleton(部署的时候动态生成字节码)
Remote接口: Hello (用户编写)
Remote接口的Weblogic实现类 HelloBean_EOImpl(EJBC生成)
Remote接口的Weblogic实现类的stub类 HelloBean_EOImpl_WLStub(部署的时候动态生成字节码)
Remote接口的Weblogic实现类的skeleton类 HelloBean_EOImpl_WLSkeleton(部署的时候动态生成字节码)
客户端只需要Hello.class和HelloHome.class这两个文件。
HelloHome home = (Home) PortableRemoteObject.narrow(ctx.lookup("Hello"), HelloHome.class);
这一行代码是从JNDI获得Home接口,但是请记住!接口是抽象的,那么home这个对象到底是什么类的对象实例呢?很简单,用toString()输出看一下就明白了,下面一行是输出结果:
HelloBean_HomeImpl_WLStub@18c458
这表明home这个通过从服务器的JNDI树上查找获得的对象实际上是HelloBean_HomeImpl_WLStub类的一个实例。
接下来客户端代码:
Hello h = home.create()
同样Hello只是一个抽象的接口,那么h对象是什么东西呢?打印一下:
HelloBean_EOImpl_WLStub@8fa0d1
原来是HelloBean_EOImpl_WLStub的一个对象实例。
用这个例子来简述一遍EJB调用过程:
首先客户端JNDI查询,服务端JNDI树上Hello这个名字实际上绑定的对象是HelloBean_HomeImpl_WLStub,所以服务端将创建HelloBean_HomeImpl_WLStub的一个对象实例,序列化返回给客户端。
于是客户端得到home对象,表面上是得到HelloHome接口的实例,实际上是进行了一次远程调用得到了HelloBean_HomeImpl_WLStub类的对象实例,别忘记了HelloBean_HomeImpl_WLStub也实现了HelloHome接口。
然后home.create()实质上就是HelloBean_HomeImpl_WLStub.create(),该方法将发送信息给HelloBean_HomeImpl_WLSkeleton,而HelloBean_HomeImpl_WLSkeleton接受到信息后,再去调用HelloBean_HomeImpl的create方法,至此完成第1次完整的RMI循环。
注意在这次RMI循环过程中,远程对象是HelloBean_HomeImpl,远程对象的接口是HelloHome,对象的stub是HelloBean_HomeImpl_WLStub,对象的skeleton是HelloBean_HomeImpl_WLSkeleton。
然后HelloBean_HomeImpl再去调用HelloBean_Impl的ejbCreate方法,而HelloBean_Impl的ejbCreate方法将负责创建或者分配一个Bean实例,并且创建一个HelloBean_EOImpl_WLStub的对象实例。
这一步比较有趣的是,在前一步RMI循环中,远程对象HelloBean_HomeImpl在客户端有一个代理类HelloBean_HomeImpl_WLStub,但在这一步,HelloBean_HomeImpl自己却充当了HelloBean_Impl的代理类,只不过HelloBean_HomeImpl不在客户端,而是在服务端,因此不进行RMI。
然后HelloBean_EOImpl_WLStub的对象实例序列化返回给客户端,这一步也很有趣,上次RMI过程,主角是HelloBean_HomeImpl和它的代理类HelloBean_HomeImpl_WLStub,但这这一次换成了HelloBean_EOImpl和它的代理类HelloBean_EOImpl_WLStub来玩了。
Hello h = home.create();h.helloWorld();
假设Hello接口有一个helloWorld远程方法,那么表面上是在调用Hello接口的helloWorld方法,实际上是在调用HelloBean_EOImpl_WLStub的helloWorld方法。
然后HelloBean_EOImpl_WLStub的helloWorld方法将发送信息给服务器上的HelloBean_EOImpl_WLSkeleton,而HelloBean_EOImpl_WLSkeleton收到信息以后,再去调用HelloBean_EOImpl的helloWorld方法。至此,完成第2次完整的RMI循环过程。
在刚才HelloBean_EOImpl是作为远程对象被调用的,它的代理类是HelloBean_EOImpl_WLStub,但现在HelloBean_EOImpl要作为HelloBean_Impl的代理类了。现在HelloBean_EOImpl去调用HelloBean_Impl的helloWorld方法。注意!HelloBean_Impl继承了HelloBean,而HelloBean中的helloWorld方法是我们亲自编写的代码,现在终于调用到了我们编写的代码了!
至此,一次EJB调用过程终于完成。在整个过程中,服务端主要要调用的类是HelloBean_Impl, HelloBean_HomeImpl,HelloBean_HomeImpl_WLSkeleton,HelloBean_EOImpl,HelloBean_EOImpl_WLSkeleton。客户端主要调用的类是HelloBean_HomeImpl_WLStub,HelloBean_EOImpl_WLStub,这两个类在客户端代码中并不会直接出现,出现在代码中的类是他们的接口HelloHome和Hello,因此客户端需要这两个接口文件,而Stub是服务器传送给他们的。
posted on 2006-01-10 13:10
TrampEagle
阅读(300)
评论(0)
编辑
收藏
所属分类:
EJB
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
知识库
C++博客
博问
管理
相关文章:
EJB技术及应用
漫谈EJB (2)
漫谈EJB (一)
《EJB调用的原理分析》
Powered by:
BlogJava
Copyright © TrampEagle