??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲激情中文,亚洲黄色网址,神马电影久久http://www.aygfsteel.com/hardson/category/13132.htmlzh-cnFri, 03 Aug 2007 01:04:53 GMTFri, 03 Aug 2007 01:04:53 GMT60EJB工作原理学习W记Q{载)http://www.aygfsteel.com/hardson/articles/130024.htmlhardsonhardsonFri, 13 Jul 2007 03:17:00 GMThttp://www.aygfsteel.com/hardson/articles/130024.htmlhttp://www.aygfsteel.com/hardson/comments/130024.htmlhttp://www.aygfsteel.com/hardson/articles/130024.html#Feedback0http://www.aygfsteel.com/hardson/comments/commentRss/130024.htmlhttp://www.aygfsteel.com/hardson/services/trackbacks/130024.htmlEJB工作原理学习W记
个h感觉该文章写得相当详l,推荐大家阅读

1 RMI工作原理
2 websphere实现
3 weblogic实现
4 理解体会

1QRMI工作原理


       RMI的本质就是实现在不同JVM之间的调?它的实现Ҏ是在两个JVM中各开一个Stub和SkeletonQ二者通过socket通信来实现参数和q回值的传递?

       有关RMI的例子代码网上可以找C,但绝大部分都是通过extend the interface java.rmi.Remote实现Q已l封装的很完善了Q不免人有N看花的感觉。下面的例子是我在《Enterprise JavaBeans》里看到的,虽然很粗p,但很直观Q利于很快了解它的工作原理?

1. 定义一个Person的接口,其中有两个business method, getAge() 和getName()

代码:

public interface Person {
     public int getAge() throws Throwable;
     public String getName() throws Throwable;
}

2. Person的实现PersonServerc?
代码:

public class PersonServer implements Person {
     int age;
     String name;

     public PersonServer(String name, int age) {
         this.age = age;
         this.name = name;
     }

     public int getAge() {
         return age;
     }

     public String getName() {
         return name;
     }
}

3. 好,我们现在要在Client机器上调用getAge()和getName()q两个business

methodQ那么就得编写相应的Stub(Client?和Skeleton(Server?E序。这是Stub的实玎ͼ
代码:

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;

public class Person_Stub implements Person {
     Socket socket;

     public Person_Stub() throws Throwable {
         // connect to skeleton
         socket = new Socket("computer_name", 9000);
     }

     public int getAge() throws Throwable {
         // pass method name to skeleton
         ObjectOutputStream outStream =
             new ObjectOutputStream(socket.getOutputStream());
         outStream.writeObject("age");
         outStream.flush();

         ObjectInputStream inStream =
             new ObjectInputStream(socket.getInputStream());
         return inStream.readInt();
     }

     public String getName() throws Throwable {
         // pass method name to skeleton
         ObjectOutputStream outStream =
             new ObjectOutputStream(socket.getOutputStream());
         outStream.writeObject("name");
         outStream.flush();

         ObjectInputStream inStream =
             new ObjectInputStream(socket.getInputStream());
         return (String)inStream.readObject();
     }
}


注意QPerson_Stub和PersonServer一P都implements

Person。它们都实现了getAge()和getName()两个business

methodQ不同的是PersonServer是真的实玎ͼPerson_Stub是徏立socketq接Qƈ向Skeleton发请求,然后通过

Skeleton调用PersonServer的方法,最后接收返回的l果?

4. Skeleton实现
代码:

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.net.ServerSocket;

public class Person_Skeleton extends Thread {
     PersonServer myServer;

     public Person_Skeleton(PersonServer server) {
         // get reference of object server
         this.myServer = server;
     }

     public void run() {
         try {
             // new socket at port 9000
             ServerSocket serverSocket = new ServerSocket(9000);
             // accept stub's request
             Socket socket = serverSocket.accept();

             while (socket != null) {
                 // get stub's request
                 ObjectInputStream inStream =
                     new ObjectInputStream(socket.getInputStream());
                 String method = (String)inStream.readObject();

                 // check method name
                 if (method.equals("age")) {
                     // execute object server's business method
                     int age = myServer.getAge();
                     ObjectOutputStream outStream =
                         new ObjectOutputStream(socket.getOutputStream());

                     // return result to stub
                     outStream.writeInt(age);
                     outStream.flush();
                 }

                 if(method.equals("name")) {
                     // execute object server's business method
                     String name = myServer.getName();
                     ObjectOutputStream outStream =
                         new ObjectOutputStream(socket.getOutputStream());

                     // return result to stub
                     outStream.writeObject(name);
                     outStream.flush();
                 }
             }
         } catch(Throwable t) {
             t.printStackTrace();
             System.exit(0);
         }
     }

     public static void main(String args []) {
         // new object server
         PersonServer person = new PersonServer("Richard", 34);

         Person_Skeleton skel = new Person_Skeleton(person);
         skel.start();
     }
}


Skeletonc?extends from ThreadQ它镉K在后台运行,随时接收client发过来的request。ƈҎ发送过来的

key去调用相应的business method?

5. 最后一个,Client的实?
代码:

public class PersonClient {
     public static void main(String [] args) {
         try {
             Person person = new Person_Stub();
             int age = person.getAge();
             String name = person.getName();
             System.out.println(name + " is " + age + " years old");
         } catch(Throwable t) {
             t.printStackTrace();
         }
     }
}


Client的本质是Q它要知道Person接口的定义,q实例一个Person_StubQ通过Stub来调用business methodQ?/p>

至于Stub怎么dServer沟通,Client׃用管了?

注意它的写法Q?
Person person = new Person_Stub();
而不?
Person_Stub person = new Person_Stub();

Z么?因ؓ要面向接口编E嘛Q呵c?/p>

//RMI实质上就是生?个类stubQskeleton来进行参数和q回值的传递,采用g递方?/font>

//cM于以前写的聊天室E序Q被传递的对象应实现java.io.Serializable接口

2Qwebsphere实现


EJBcM?nbsp;   
q里l合WebSphere来讲讲各个类的调用关pd?

假定我们要创Z个读取User信息的SessionBeanQ需要我们写的有3个文Ӟ
1. UserServiceHome.java
Home接口

2. UserService.java
Remote接口

3. UserServiceBean.java
Bean实现

WSAD最l会生成10个class。其?个是什么呢Q我们一个一个数q来Q?

4. _UserServiceHome_Stub.java
q个当然是Home接口在Client?动态加?的StubcMQ它implements UserServiceHome?

5. _EJSRemoteStatelessUserServiceHome_a940aa04_Tie.java
Home接口在Server端的Skeletonc,"a940aa04"应该是随机生成的Q所有其他的相关class名里都会有这个标?/p>

ԌTie是Corba对Skeleton的叫法?

6. EJSRemoteStatelessUserServiceHome_a940aa04.java
Home接口在Server端的实现Q当Ӟ它也implements UserServiceHome?

7. EJSStatelessUserServiceHomeBean_a940aa04.java
?6调用Qcreate _UserService_Stub?Z?6不能直接create _UserService_Stub呢?后面再讲?

8. _UserService_Stub.java
Remote接口在Client?动态加?的StubcR它implements UserService?

9. _EJSRemoteStatelessUserService_a940aa04_Tie.java
Remote接口在Server端的SkeletoncR?

10. EJSRemoteStatelessUserService_a940aa04.java
Remote接口在Server端的实现Q当Ӟ它也implements UserService。ƈ且,它负责调用UserServiceBean—?/p>

也就是我们所写的Bean实现cZ—里面的business method?

那么Q各个类之间的调用关pd底是怎么L呢?单的_是两次RMI循环?

    
   

W一个RMI循环    
先来看看Client端的E序是怎么写的Q?

代码:

try {
     InitialContext ctx = new InitialContext();

     //W一?
     UserServiceHome home =
         (UserServiceHome) PortableRemoteObject.narrow(
             ctx.lookup(JNDIString),
             UserServiceHome.class);

     //home: _UserServiceHome_Stub
     System.out.println(home.toString());

     //W二?
     UserService object = home.create();

     //ojbect: _UserService_Stub
     System.out.println(object.toString());

     //W三?
     int userId = 1;
     UserInfo ui = object.getUserInfo(userId);
}


在第一步之后,我们得到了一个UserServiceHome(interface)定义的对象homeQ那么,home到底是哪个class?/p>

instance呢?用debug看一下,知道了home原来是_UserServiceHome_Stub的实例?

从第二步开始,是我们的关注所在,虽然只有单的一行代码,
UserService object = home.create();
但是他背后的pȝ是怎么q做的呢Q我们进入代码来看吧Q?

1. 调用home.create()
代码:

UserServiceHome home;
UserService obj = home.create();


2. 实际是调用_UserServiceHome_Stub.create()Q在q个Ҏ里面QStub向Skeleton发送了一个create的字?/p>

Q?
代码:

org.omg.CORBA.portable.OutputStream out = _request("create", true);
in = (org.omg.CORBA_2_3.portable.InputStream)_invoke(out);


3. Server端的Skeleton接收Stub发来的requestQƈ调用相应的方法:
代码:

_EJSRemoteStatelessUserServiceHome_a940aa04_Tie._invoke() {
     ......
     switch (method.length()) {
         case 6:
             if (method.equals("create")) {
                 return create(in, reply);
             }
         ......
     }
}


代码:

_EJSRemoteStatelessUserServiceHome_a940aa04_Tie.create() {
     EJSRemoteStatelessUserServiceHome_a940aa04 target = null;
     result = target.create();
     org.omg.CORBA.portable.OutputStream out = reply.createReply();
     Util.writeRemoteObject(out,result);
     return out;
}


4. Skeleton调用的是UserServiceHome的Server端实现类的createҎ
代码:

EJSRemoteStatelessUserServiceHome_a940aa04.create() {
     UserService _EJS_result;
     _EJS_result = EJSStatelessUserServiceHomeBean_a940aa04.create();
}


5. #4又调用EJSStatelessUserServiceHomeBean_a940aa04.create()
代码:

     UserService result = super.createWrapper(new BeanId(this, null));


xQ我们终于结束了W一个RMI循环Qƈ得到了Remote接口UserService的Stubc_UserService_StubQ就?5

里面的result?

q里有一个问题,Z?4不直接create _UserService_StubQ而又转了一?5的手呢?因ؓ#4 extends from

EJSWrapperQ它没有能力create StubQ因此必d助#5Qwhich extends from EJSHomeQ这h可以生成一?/p>

Stub。如果不是ؓ了生成这个StubQ应该可以不?5q一步?
   
    

W二个RMI循环    
OK, now we got the object which is instanceOf _UserService_Stub, and implements UserService

现在我们的Client端走到第三步了:
UserInfo ui = object.getUserInfo(userId);

l箋看代码,开始第二个RMI循环Q?

1. 调用object.getUserInfo()
代码:

UserService object;
object.getUserInfo(userId);


2. 实际是调用_UserService_Stub.getUserInfo(int

arg0)Q在q个Ҏ里面QStub向Skeleton发送了一个getUserInfo的字串和arg0q个参数Q?

代码:

org.omg.CORBA.portable.OutputStream out = _request("getUserInfo", true);
out.write_long(arg0);
in = (org.omg.CORBA_2_3.portable.InputStream)_invoke(out);


3. Server端的Skeleton接收Stub发来的requestQƈ调用相应的方法:
代码:

_EJSRemoteStatelessUserService_a940aa04_Tie._invoke() {
     switch (method.charAt(5))
     {
         case 83:
             if (method.equals("getUserInfo")) {
                 return getUserInfo(in, reply);
             }
         ......
     }
}

_EJSRemoteStatelessUserService_a940aa04_Tie.getUserInfo() {
     EJSRemoteStatelessUserService_a940aa04 target = null;
     int arg0 = in.read_long();
     UserDTO result = target.getUserInfo(arg0);
     org.omg.CORBA_2_3.portable.OutputStream out = reply.createReply();
     out.write_value(result,UserDTO.class);
     return out;
}


4. Skeleton调用的是UserService的Server端实现类的getUserInfoҎ
代码:

EJSRemoteStatelessUserService_a940aa04.getUserInfo() {
     UserServiceBean _EJS_beanRef = container.preInvoke(this, 0, _EJS_s);
     _EJS_result = _EJS_beanRef.getUserInfo(id);
}


最后的最后,#4l于调用了我们写的UserServiceBean里的getUserInfoҎQ这才是我们真正惌d的事?/p>

?

xQ第二个RMI循环也终于结束了?
   
    

调用程?nbsp;   
回顾一下上面的分析Q可以很清晰的看CơRMI循环的过E,下图(见链?描述了整个流E:

http://www.pbase.com/image/27229257

黄色?Q?Q?0是程序员要写的,其余是系l生成的?

#1是Home interface, #2?4都implements 了它?
#6是Remote interface, #7?9都implements 了它?
#10是Bean实现?


3Qweblogic实现
一个远E对象至要包括4个class文gQ远E对象;q程对象的接口;实现q程接口的对象的stubQ对象的ske

letonq?个class文g?/p>

在EJB中则臛_要包?0个classQ?/p>

Beanc,特定App Server的Bean实现c?/p>

Bean的remote接口Q特定App Server的remote接口实现c,特定App

Server的remote接口的实现类的stubcdskeletonc?/p>

Bean的home接口Q特定App Server的home接口实现c,特定App

Server的home接口的实现类的stubcdskeletonc?/p>

和RMI不同的是QEJB中这10个class真正需要用L写的只有3个,分别是Beancd它的remote接口Qhome接口

Q至于其它的7个class到底是怎么生成Q被打包在什么地方,或者是否需要更多的cLӞ会根据不同的App

Server表现出比较大的差异,不能一概而论?/p>

拿Weblogic的来说吧QWeblogic的Bean实现c,以及两个接口的Weblogic的实现类是在ejbc的时候被打包到EJB

的jar包里面的Q这3个class文g可以看到。而home接口和remote接口的Weblogic的实现类的stubcdskeleton

cL在EJB被部|到Weblogic的时候,由Weblogic动态生成stubcdSkeletoncȝ字节码,因此看不到这4个类

文g?/p>

对于一ơ客Lq程调用EJBQ要l过两个q程对象的多ơRMI循环。首先是通过JNDI查找Home接口Q获得Home

接口的实现类Q这个过E其实相当复杂,首先是找到Home接口的Weblogic实现c,然后创徏一个Home接口的Web

logic实现cȝstubcȝ对象实例Q将它序列化传送给客户端(注意stubcȝ实例是在W?ơRMI循环中,由服?/p>

器动态发送给客户端的Q因此不需要客L保存Home接口的Weblogic实现cȝstubc)Q最后客L获得该stu

bcȝ对象实例Q普通的RMI需要在客户端保存stubc,而EJB不需要,因ؓ服务器会把stubcȝ对象实例发送给

客户端)?/p>

客户端拿到服务器l它的Home接口的Weblogic实现cȝstubcd象实例以后,调用stubcȝcreateҎQ?在代

码上是home.create()Q但是后台要做很多事?,于是l过W?ơRMI循环Q在服务器端QHome接口的Weblogic

实现cȝskeletoncL到stubcȝ调用信息后,由它再去调用Home接口的Weblogic实现cȝcreateҎ?/p>

在服务端QHome接口的Weblogic实现cȝcreateҎ再去调用BeancȝWeblogic实现cȝejbCreateҎQ在?/p>

务端创徏或者分配一个EJB实例Q然后将q个EJB实例的远E接口的Weblogic实现cȝstubcd象实例序列化?/p>

送给客户端?/p>

客户端收到remote接口的Weblogic实现cȝstubcȝ对象实例Q对该对象实例的Ҏ调用Q在客户端代码中?/p>

际上是对remote接口的调用)Q将传送给服务器端remote接口的Weblogic实现cȝskeletoncd象,而skele

toncd象再调用相应的remote接口的Weblogic实现c,然后remote接口的Weblogic实现cd去调用BeancȝWe

blogic实现c,如此完成一ơEJB对象的远E调用?/p>

看了一遍帖子,感觉q是没有说太清楚Q既然写了帖子,想d把它说清楚?/p>

先拿普通RMI来说Q有4个classQ分别是q程对象Q对象的接口Q对象的stubcdskeletoncR而对象本w和?/p>

象的stubcd旉实现了接口类。而我们在客户端代码调用远E对象的时候,虽然在代码中操纵接口Q实质上

是在操纵stubc,例如Q?/p>

接口c:Hello

q程对象QHello_Server

stubc:Hello_Stub

skeletonc:Hello_Skeleton

客户端代码要q样写:

Hello h = new Hello_Stub();
h.getString();

我们不会q样写:

Hello_Stub h = new Hello_Stub();
h.getString();

因ؓ使用接口适用性更q,q更换了接口实现类Q也不需要更改代码。因此客L需要Hello.class和Hello_

Stub.classq两个文件。但是对于EJB来说Q就不需要Hello_Stub.classQ因为服务器会发送给它,但是Hello.

class文g客户端是省不了的Q必L。表面上我们的客L代码在操UHelloQ但别忘CHello只是一个接?/p>

Q抽象的Q实质上是在操纵Hello_Stub?/p>

拿Weblogic上的EJB举例子,10个class分别是:

Beanc:HelloBean Q用L写)
BeancȝWeblogic实现c:HelloBean_Impl QEJBC生成Q?br> Home接口QHelloHome Q用L写)
Home接口的Weblogic实现c?((Hello Bean))_HomeImplQEJBC生成Q?br> Home接口的Weblogic实现cȝstubc?((Hello Bean))_HomeImpl_WLStubQ部|的时候动态生成字节码Q?br> Home接口的Weblogic实现cȝskeletonc?((Hello Bean))_HomeImpl_WLSkeletonQ部|的时候动态生成字节码

Q?br> Remote接口Q?Hello Q用L写)
Remote接口的Weblogic实现c?((Hello Bean))_EOImplQEJBC生成Q?br> Remote接口的Weblogic实现cȝstubc?((Hello Bean))_EOImpl_WLStubQ部|的时候动态生成字节码Q?br> Remote接口的Weblogic实现cȝskeletonc?((Hello Bean))_EOImpl_WLSkeletonQ部|的时候动态生成字节码

Q?/p>

客户端只需要Hello.class和HelloHome.classq两个文件?/p>

((Hello Home)) home = (Home) ((Portable Remote Object)).narrow(ctx.lookup("Hello"), ((Hello

Home)).class);

q一行代码是从JNDI获得Home接口Q但是请CQ接口是抽象的,那么homeq个对象到底是什么类的对象实?/p>

呢?很简单,用toString()输出看一下就明白了,下面一行是输出l果Q?/p>

((Hello Bean))_HomeImpl_WLStub@18c458

q表明homeq个通过从服务器的JNDI树上查找获得的对象实际上是HelloBean_HomeImpl_WLStubcȝ一个实例?/p>

接下来客L代码Q?/p>

Hello h = home.create()

同样Hello只是一个抽象的接口Q那么h对象是什么东西呢Q打C下:

((Hello Bean))_EOImpl_WLStub@8fa0d1

原来是HelloBean_EOImpl_WLStub的一个对象实例?/p>

用这个例子来qC遍EJB调用q程Q?/p>

首先客户端JNDI查询Q服务端JNDI树上Helloq个名字实际上绑定的对象是HelloBean_HomeImpl_WLStubQ所?/p>

服务端将创徏HelloBean_HomeImpl_WLStub的一个对象实例,序列化返回给客户端?/p>

于是客户端得到home对象Q表面上是得到HelloHome接口的实例,实际上是q行了一ơ远E调用得CHelloBea

n_HomeImpl_WLStubcȝ对象实例Q别忘记了HelloBean_HomeImpl_WLStub也实CHelloHome接口?/p>

然后home.create()实质上就是HelloBean_HomeImpl_WLStub.create()Q该Ҏ发送信息给HelloBean_HomeIm

pl_WLSkeletonQ而HelloBean_HomeImpl_WLSkeleton接受C息后Q再去调用HelloBean_HomeImpl的create?/p>

法,x完成W?ơ完整的RMI循环?/p>

注意在这ơRMI循环q程中,q程对象是HelloBean_HomeImplQ远E对象的接口是HelloHomeQ对象的stub是Hel

loBean_HomeImpl_WLStubQ对象的skeleton是HelloBean_HomeImpl_WLSkeleton?/p>

然后HelloBean_HomeImpl再去调用HelloBean_Impl的ejbCreateҎQ而HelloBean_Impl的ejbCreateҎ负

责创建或者分配一个Bean实例Qƈ且创Z个HelloBean_EOImpl_WLStub的对象实例?/p>

q一步比较有的是,在前一步RMI循环中,q程对象HelloBean_HomeImpl在客L有一个代理类HelloBean_Ho

meImpl_WLStubQ但在这一步,HelloBean_HomeImpl自己却充当了HelloBean_Impl的代理类Q只不过HelloBean_

HomeImpl不在客户端,而是在服务端Q因此不q行RMI?/p>

然后HelloBean_EOImpl_WLStub的对象实例序列化q回l客LQ这一步也很有,上次RMIq程Q主角是Hello

Bean_HomeImpl和它的代理类HelloBean_HomeImpl_WLStubQ但q这一ơ换成了HelloBean_EOImpl和它的代理类H

elloBean_EOImpl_WLStub来玩了?/p>

Hello h = home.create();h.helloWorld();

假设Hello接口有一个helloWorldq程ҎQ那么表面上是在调用Hello接口的helloWorldҎQ实际上是在?/p>

用HelloBean_EOImpl_WLStub的helloWorldҎ?/p>

然后HelloBean_EOImpl_WLStub的helloWorldҎ发送信息给服务器上的HelloBean_EOImpl_WLSkeletonQ而H

elloBean_EOImpl_WLSkeleton收到信息以后Q再去调用HelloBean_EOImpl的helloWorldҎ。至此,完成W??/p>

完整的RMI循环q程?/p>

在刚才HelloBean_EOImpl是作E对象被调用的,它的代理cLHelloBean_EOImpl_WLStubQ但现在HelloBea

n_EOImpl要作为HelloBean_Impl的代理类了。现在HelloBean_EOImpl去调用HelloBean_Impl的helloWorldҎ

。注意!HelloBean_Impll承了HelloBeanQ而HelloBean中的helloWorldҎ是我们亲自编写的代码Q现在终

于调用到了我们编写的代码了!

xQ一ơEJB调用q程l于完成。在整个q程中,服务端主要要调用的类是HelloBean_ImplQ?Hello

Bean?_HomeImplQHelloBean_HomeImpl_WLSkeletonQHelloBean_EOImplQHelloBean_EOImpl_WLSkeleton。客

L主要调用的类是HelloBean_HomeImpl_WLStubQHelloBean_EOImpl_WLStubQ这两个cd客户端代码中q不

会直接出玎ͼ出现在代码中的类是他们的接口HelloHome和HelloQ因此客L需要这两个接口文gQ而Stub?/p>

服务器传送给他们的?/p>

4 理解体会
单讲Q就是ؓ了适应分布式开发的需要?

首先Q回到我最后给出的程图?
http://www.pbase.com/nobo123/image/27229257

Client端最原始的冲动,肯定是能直接调用#10.UserServiceBeanq了。那么第一个问题来了,
Client和Server不在一个JVM里?

q好办,我们不是有RMI吗,好,q个问题p么解决了Q?
1. UserServiceBeanInterface.getUserInfo()
2. UserServiceBeanStub
3. UserServiceBeanSkeleton
4. UserServiceBean

用着用着Q第二个问题来了Q?
UserServiceBean只有人用Q没人管理,transaction logic, security logic, bean instance pooling logic

q些不得不考虑的问题Q出水面了?

OKQ我们想到用一个delegateQEJBObjectQ来q行所有这些logic的管理。client和EJBObject打交道,EJBObj

ect调用UserServiceBean?

注意Q这个EJBObject也是一个InterfaceQ?6.UserServiceq个interface正是从它extends而来。ƈ且EJBObje

ct所理的这些logicQ正是AppServer的一部分?

现在的流E变ZQ?
EJBObject
1. UserService.getUserInfo()
2. UserServiceStub
3. UserServiceSkeleton
4. UserServiceImp
5. UserServiceBean

q已l和整幅N?6, #7, #8, #9, #10一一对应了?

现在能满x们的需求了吗?不,W三个问题又来了Q?
既然是分布式开发,那么我当然没理由只用一个Specified ServerQ我可能需要用到好几个不同的ServerQ?/p>

且EJBObject也需要管理呀

OKQؓ了适应你的需要,我们q得加再一个HomeObjectQ首先它来决定用哪个Server(当然Q是׃用JNDI

String讑֮?Q其ơ,它来理EJBObject?

注意Q这个EJBHome也是一个InterfaceQ?1.UserServiceHomeq个interface正是从它extends而来。ƈ且EJBHo

me理EJBObject的logicQ也是AppServer的一部分?

现在的调用次序是
1. EJBHome.create()
2. EJBHomeStub
3. EJBHomeSkeleton
4. EJBHomeImp(EJSWrapper)
5. EJSHome

得到EJBObject

6. UserService.getUserInfo()
7. UserServiceStub
8. UserServiceSkeleton
9. UserServiceImp
10. UserServiceBean

现在已经完全和流E图的调用顺序一致了?

//EJB的基是RMI IIOP,原理q不是很难,关键是实现v来比较绕Q一个简单的功能要用10个(或更多)cL实现Q但每一个都不是多余的?/strong>

//EJB的这U模式(或说RMIQ完全屏蔽了底层的网l,q很好的实现了对业务代码的保护?/strong>



hardson 2007-07-13 11:17 发表评论
]]>
վ֩ģ壺 | ̶| 㽭ʡ| Ԫ| | | ۲| | | ɽ| | ɽ| ͭ| | | մ| Դ| ־| | | ׿| ̨| | Ϊ| | | ̨| | | | | ̨| | ³| | | | ȳ| | | |