欢迎光临
我们一直在努力

robbin写的EJB调用的原理分析-JSP教程,Java技巧及代码

建站超值云服务器,限时71元/月

一个远程对象至少要包括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是服务器传送给他们的。

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » robbin写的EJB调用的原理分析-JSP教程,Java技巧及代码
分享到: 更多 (0)

相关推荐

  • 暂无文章