<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    EJB工作原理學習筆記(轉載)

    EJB工作原理學習筆記
    個人感覺該文章寫得相當詳細,推薦大家閱讀

    1 RMI工作原理
    2 websphere實現(xiàn)
    3 weblogic實現(xiàn)
    4 理解體會

    1:RMI工作原理


           RMI的本質就是實現(xiàn)在不同JVM之間的調用,它的實現(xiàn)方法就是在兩個JVM中各開一個Stub和Skeleton,二者通過socket通信來實現(xiàn)參數(shù)和返回值的傳遞。

           有關RMI的例子代碼網(wǎng)上可以找到不少,但絕大部分都是通過extend the interface java.rmi.Remote實現(xiàn),已經封裝的很完善了,不免使人有霧里看花的感覺。下面的例子是我在《Enterprise JavaBeans》里看到的,雖然很粗糙,但很直觀,利于很快了解它的工作原理。

    1. 定義一個Person的接口,其中有兩個business method, getAge() 和getName()

    代碼:

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

    2. Person的實現(xiàn)PersonServer類
    代碼:

    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. 好,我們現(xiàn)在要在Client機器上調用getAge()和getName()這兩個business

    method,那么就得編寫相應的Stub(Client端)和Skeleton(Server端)程序。這是Stub的實現(xiàn):
    代碼:

    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();
         }
    }


    注意,Person_Stub和PersonServer一樣,都implements

    Person。它們都實現(xiàn)了getAge()和getName()兩個business

    method,不同的是PersonServer是真的實現(xiàn),Person_Stub是建立socket連接,并向Skeleton發(fā)請求,然后通過

    Skeleton調用PersonServer的方法,最后接收返回的結果。

    4. Skeleton實現(xiàn)
    代碼:

    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();
         }
    }


    Skeleton類 extends from Thread,它長駐在后臺運行,隨時接收client發(fā)過來的request。并根據(jù)發(fā)送過來的

    key去調用相應的business method。

    5. 最后一個,Client的實現(xiàn)
    代碼:

    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的本質是,它要知道Person接口的定義,并實例一個Person_Stub,通過Stub來調用business method,

    至于Stub怎么去和Server溝通,Client就不用管了。

    注意它的寫法:
    Person person = new Person_Stub();
    而不是
    Person_Stub person = new Person_Stub();

    為什么?因為要面向接口編程嘛,呵呵。

    //RMI實質上就是生成2個類stub,skeleton來進行參數(shù)和返回值的傳遞,采用值傳遞方式

    //類似于以前寫的聊天室程序,被傳遞的對象應實現(xiàn)java.io.Serializable接口

    2:websphere實現(xiàn)


    EJB類一覽    
    這里結合WebSphere來講講各個類的調用關系吧。

    假定我們要創(chuàng)建一個讀取User信息的SessionBean,需要我們寫的有3個文件:
    1. UserServiceHome.java
    Home接口

    2. UserService.java
    Remote接口

    3. UserServiceBean.java
    Bean實現(xiàn)

    WSAD最終會生成10個class。其它7個是什么呢?我們一個一個數(shù)過來:

    4. _UserServiceHome_Stub.java
    這個當然就是Home接口在Client端(動態(tài)加載)的Stub類了,它implements UserServiceHome。

    5. _EJSRemoteStatelessUserServiceHome_a940aa04_Tie.java
    Home接口在Server端的Skeleton類,"a940aa04"應該是隨機生成的,所有其他的相關class名里都會有這個標志

    串,Tie是Corba對Skeleton的叫法。

    6. EJSRemoteStatelessUserServiceHome_a940aa04.java
    Home接口在Server端的實現(xiàn),當然,它也implements UserServiceHome。

    7. EJSStatelessUserServiceHomeBean_a940aa04.java
    由#6調用,create _UserService_Stub。(為什么#6不能直接create _UserService_Stub呢?后面再講。)

    8. _UserService_Stub.java
    Remote接口在Client端(動態(tài)加載)的Stub類。它implements UserService。

    9. _EJSRemoteStatelessUserService_a940aa04_Tie.java
    Remote接口在Server端的Skeleton類。

    10. EJSRemoteStatelessUserService_a940aa04.java
    Remote接口在Server端的實現(xiàn),當然,它也implements UserService。并且,它負責調用UserServiceBean——

    也就是我們所寫的Bean實現(xiàn)類——里面的business method。

    那么,各個類之間的調用關系到底是怎么樣的呢?簡單的說,就是兩次RMI循環(huán)。

        
       

    第一個RMI循環(huán)    
    先來看看Client端的程序是怎么寫的:

    代碼:

    try {
         InitialContext ctx = new InitialContext();

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

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

         //第二步
         UserService object = home.create();

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

         //第三步
         int userId = 1;
         UserInfo ui = object.getUserInfo(userId);
    }


    在第一步之后,我們得到了一個UserServiceHome(interface)定義的對象home,那么,home到底是哪個class的

    instance呢?用debug看一下,知道了home原來就是_UserServiceHome_Stub的實例。

    從第二步開始,就是我們的關注所在,雖然只有簡單的一行代碼,
    UserService object = home.create();
    但是他背后的系統(tǒng)是怎么運做的呢?我們進入代碼來看吧:

    1. 調用home.create()
    代碼:

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


    2. 實際是調用_UserServiceHome_Stub.create(),在這個方法里面,Stub向Skeleton發(fā)送了一個create的字串


    代碼:

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


    3. Server端的Skeleton接收Stub發(fā)來的request,并調用相應的方法:
    代碼:

    _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端實現(xiàn)類的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));


    至此,我們終于結束了第一個RMI循環(huán),并得到了Remote接口UserService的Stub類_UserService_Stub,就是#5

    里面的result。

    這里有一個問題,為什么#4不直接create _UserService_Stub,而又轉了一道#5的手呢?因為#4 extends from

    EJSWrapper,它沒有能力create Stub,因此必須借助#5,which extends from EJSHome,這樣才可以生成一個

    Stub。如果不是為了生成這個Stub,應該可以不走#5這一步。
       
        

    第二個RMI循環(huán)    
    OK, now we got the object which is instanceOf _UserService_Stub, and implements UserService

    現(xiàn)在我們的Client端走到第三步了:
    UserInfo ui = object.getUserInfo(userId);

    繼續(xù)看代碼,開始第二個RMI循環(huán):

    1. 調用object.getUserInfo()
    代碼:

    UserService object;
    object.getUserInfo(userId);


    2. 實際是調用_UserService_Stub.getUserInfo(int

    arg0),在這個方法里面,Stub向Skeleton發(fā)送了一個getUserInfo的字串和arg0這個參數(shù):

    代碼:

    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發(fā)來的request,并調用相應的方法:
    代碼:

    _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端實現(xiàn)類的getUserInfo方法
    代碼:

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


    最后的最后,#4終于調用了我們寫的UserServiceBean里的getUserInfo方法,這才是我們真正想要去做的事情

    至此,第二個RMI循環(huán)也終于結束了。
       
        

    調用流程圖    
    回顧一下上面的分析,可以很清晰的看到兩次RMI循環(huán)的過程,下圖(見鏈接)描述了整個流程:

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

    黃色的1,6,10是程序員要寫的,其余是系統(tǒng)生成的。

    #1是Home interface, #2和#4都implements 了它。
    #6是Remote interface, #7和#9都implements 了它。
    #10是Bean實現(xiàn)。


    3:weblogic實現(xiàn)
    一個遠程對象至少要包括4個class文件:遠程對象;遠程對象的接口;實現(xiàn)遠程接口的對象的stub;對象的ske

    leton這4個class文件。

    在EJB中則至少要包括10個class:

    Bean類,特定App Server的Bean實現(xiàn)類

    Bean的remote接口,特定App Server的remote接口實現(xiàn)類,特定App

    Server的remote接口的實現(xiàn)類的stub類和skeleton類

    Bean的home接口,特定App Server的home接口實現(xiàn)類,特定App

    Server的home接口的實現(xiàn)類的stub類和skeleton類

    和RMI不同的是,EJB中這10個class真正需要用戶編寫的只有3個,分別是Bean類和它的remote接口,home接口

    ,至于其它的7個class到底是怎么生成,被打包在什么地方,或者是否需要更多的類文件,會根據(jù)不同的App

    Server表現(xiàn)出比較大的差異,不能一概而論。

    拿Weblogic的來說吧,Weblogic的Bean實現(xiàn)類,以及兩個接口的Weblogic的實現(xiàn)類是在ejbc的時候被打包到EJB

    的jar包里面的,這3個class文件可以看到。而home接口和remote接口的Weblogic的實現(xiàn)類的stub類和skeleton

    類是在EJB被部署到Weblogic的時候,由Weblogic動態(tài)生成stub類和Skeleton類的字節(jié)碼,因此看不到這4個類

    文件。

    對于一次客戶端遠程調用EJB,要經過兩個遠程對象的多次RMI循環(huán)。首先是通過JNDI查找Home接口,獲得Home

    接口的實現(xiàn)類,這個過程其實相當復雜,首先是找到Home接口的Weblogic實現(xiàn)類,然后創(chuàng)建一個Home接口的Web

    logic實現(xiàn)類的stub類的對象實例,將它序列化傳送給客戶端(注意stub類的實例是在第1次RMI循環(huán)中,由服務

    器動態(tài)發(fā)送給客戶端的,因此不需要客戶端保存Home接口的Weblogic實現(xiàn)類的stub類),最后客戶端獲得該stu

    b類的對象實例(普通的RMI需要在客戶端保存stub類,而EJB不需要,因為服務器會把stub類的對象實例發(fā)送給

    客戶端)。

    客戶端拿到服務器給它的Home接口的Weblogic實現(xiàn)類的stub類對象實例以后,調用stub類的create方法,(在代

    碼上就是home.create(),但是后臺要做很多事情),于是經過第2次RMI循環(huán),在服務器端,Home接口的Weblogic

    實現(xiàn)類的skeleton類收到stub類的調用信息后,由它再去調用Home接口的Weblogic實現(xiàn)類的create方法。

    在服務端,Home接口的Weblogic實現(xiàn)類的create方法再去調用Bean類的Weblogic實現(xiàn)類的ejbCreate方法,在服

    務端創(chuàng)建或者分配一個EJB實例,然后將這個EJB實例的遠程接口的Weblogic實現(xiàn)類的stub類對象實例序列化發(fā)

    送給客戶端。

    客戶端收到remote接口的Weblogic實現(xiàn)類的stub類的對象實例,對該對象實例的方法調用(在客戶端代碼中實

    際上就是對remote接口的調用),將傳送給服務器端remote接口的Weblogic實現(xiàn)類的skeleton類對象,而skele

    ton類對象再調用相應的remote接口的Weblogic實現(xiàn)類,然后remote接口的Weblogic實現(xiàn)類再去調用Bean類的We

    blogic實現(xiàn)類,如此就完成一次EJB對象的遠程調用。

    看了一遍帖子,感覺還是沒有說太清楚,既然寫了帖子,就想徹底把它說清楚。

    先拿普通RMI來說,有4個class,分別是遠程對象,對象的接口,對象的stub類和skeleton類。而對象本身和對

    象的stub類同時都實現(xiàn)了接口類。而我們在客戶端代碼調用遠程對象的時候,雖然在代碼中操縱接口,實質上

    是在操縱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();

    因為使用接口適用性更廣,就算更換了接口實現(xiàn)類,也不需要更改代碼。因此客戶端需要Hello.class和Hello_

    Stub.class這兩個文件。但是對于EJB來說,就不需要Hello_Stub.class,因為服務器會發(fā)送給它,但是Hello.

    class文件客戶端是省不了的,必須有。表面上我們的客戶端代碼在操縱Hello,但別忘記了Hello只是一個接口

    ,抽象的,實質上是在操縱Hello_Stub。

    拿Weblogic上的EJB舉例子,10個class分別是:

    Bean類:HelloBean (用戶編寫)
    Bean類的Weblogic實現(xiàn)類:HelloBean_Impl (EJBC生成)
    Home接口:HelloHome (用戶編寫)
    Home接口的Weblogic實現(xiàn)類 ((Hello Bean))_HomeImpl(EJBC生成)
    Home接口的Weblogic實現(xiàn)類的stub類 ((Hello Bean))_HomeImpl_WLStub(部署的時候動態(tài)生成字節(jié)碼)
    Home接口的Weblogic實現(xiàn)類的skeleton類 ((Hello Bean))_HomeImpl_WLSkeleton(部署的時候動態(tài)生成字節(jié)碼


    Remote接口: Hello (用戶編寫)
    Remote接口的Weblogic實現(xiàn)類 ((Hello Bean))_EOImpl(EJBC生成)
    Remote接口的Weblogic實現(xiàn)類的stub類 ((Hello Bean))_EOImpl_WLStub(部署的時候動態(tài)生成字節(jié)碼)
    Remote接口的Weblogic實現(xiàn)類的skeleton類 ((Hello Bean))_EOImpl_WLSkeleton(部署的時候動態(tài)生成字節(jié)碼

    客戶端只需要Hello.class和HelloHome.class這兩個文件。

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

    Home)).class);

    這一行代碼是從JNDI獲得Home接口,但是請記住!接口是抽象的,那么home這個對象到底是什么類的對象實例

    呢?很簡單,用toString()輸出看一下就明白了,下面一行是輸出結果:

    ((Hello Bean))_HomeImpl_WLStub@18c458

    這表明home這個通過從服務器的JNDI樹上查找獲得的對象實際上是HelloBean_HomeImpl_WLStub類的一個實例。

    接下來客戶端代碼:

    Hello h = home.create()

    同樣Hello只是一個抽象的接口,那么h對象是什么東西呢?打印一下:

    ((Hello Bean))_EOImpl_WLStub@8fa0d1

    原來是HelloBean_EOImpl_WLStub的一個對象實例。

    用這個例子來簡述一遍EJB調用過程:

    首先客戶端JNDI查詢,服務端JNDI樹上Hello這個名字實際上綁定的對象是HelloBean_HomeImpl_WLStub,所以

    服務端將創(chuàng)建HelloBean_HomeImpl_WLStub的一個對象實例,序列化返回給客戶端。

    于是客戶端得到home對象,表面上是得到HelloHome接口的實例,實際上是進行了一次遠程調用得到了HelloBea

    n_HomeImpl_WLStub類的對象實例,別忘記了HelloBean_HomeImpl_WLStub也實現(xiàn)了HelloHome接口。

    然后home.create()實質上就是HelloBean_HomeImpl_WLStub.create(),該方法將發(fā)送信息給HelloBean_HomeIm

    pl_WLSkeleton,而HelloBean_HomeImpl_WLSkeleton接受到信息后,再去調用HelloBean_HomeImpl的create方

    法,至此完成第1次完整的RMI循環(huán)。

    注意在這次RMI循環(huán)過程中,遠程對象是HelloBean_HomeImpl,遠程對象的接口是HelloHome,對象的stub是Hel

    loBean_HomeImpl_WLStub,對象的skeleton是HelloBean_HomeImpl_WLSkeleton。

    然后HelloBean_HomeImpl再去調用HelloBean_Impl的ejbCreate方法,而HelloBean_Impl的ejbCreate方法將負

    責創(chuàng)建或者分配一個Bean實例,并且創(chuàng)建一個HelloBean_EOImpl_WLStub的對象實例。

    這一步比較有趣的是,在前一步RMI循環(huán)中,遠程對象HelloBean_HomeImpl在客戶端有一個代理類HelloBean_Ho

    meImpl_WLStub,但在這一步,HelloBean_HomeImpl自己卻充當了HelloBean_Impl的代理類,只不過HelloBean_

    HomeImpl不在客戶端,而是在服務端,因此不進行RMI。

    然后HelloBean_EOImpl_WLStub的對象實例序列化返回給客戶端,這一步也很有趣,上次RMI過程,主角是Hello

    Bean_HomeImpl和它的代理類HelloBean_HomeImpl_WLStub,但這這一次換成了HelloBean_EOImpl和它的代理類H

    elloBean_EOImpl_WLStub來玩了。

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

    假設Hello接口有一個helloWorld遠程方法,那么表面上是在調用Hello接口的helloWorld方法,實際上是在調

    用HelloBean_EOImpl_WLStub的helloWorld方法。

    然后HelloBean_EOImpl_WLStub的helloWorld方法將發(fā)送信息給服務器上的HelloBean_EOImpl_WLSkeleton,而H

    elloBean_EOImpl_WLSkeleton收到信息以后,再去調用HelloBean_EOImpl的helloWorld方法。至此,完成第2次

    完整的RMI循環(huán)過程。

    在剛才HelloBean_EOImpl是作為遠程對象被調用的,它的代理類是HelloBean_EOImpl_WLStub,但現(xiàn)在HelloBea

    n_EOImpl要作為HelloBean_Impl的代理類了。現(xiàn)在HelloBean_EOImpl去調用HelloBean_Impl的helloWorld方法

    。注意!HelloBean_Impl繼承了HelloBean,而HelloBean中的helloWorld方法是我們親自編寫的代碼,現(xiàn)在終

    于調用到了我們編寫的代碼了!

    至此,一次EJB調用過程終于完成。在整個過程中,服務端主要要調用的類是HelloBean_Impl, Hello

    Bean?_HomeImpl,HelloBean_HomeImpl_WLSkeleton,HelloBean_EOImpl,HelloBean_EOImpl_WLSkeleton。客

    戶端主要調用的類是HelloBean_HomeImpl_WLStub,HelloBean_EOImpl_WLStub,這兩個類在客戶端代碼中并不

    會直接出現(xiàn),出現(xiàn)在代碼中的類是他們的接口HelloHome和Hello,因此客戶端需要這兩個接口文件,而Stub是

    服務器傳送給他們的。

    4 理解體會
    簡單講,就是為了適應分布式開發(fā)的需要。

    首先,回到我最后給出的流程圖。
    http://www.pbase.com/nobo123/image/27229257

    Client端最原始的沖動,肯定是能直接調用#10.UserServiceBean就爽了。那么第一個問題來了,
    Client和Server不在一個JVM里。

    這好辦,我們不是有RMI嗎,好,這個問題就這么解決了:
    1. UserServiceBeanInterface.getUserInfo()
    2. UserServiceBeanStub
    3. UserServiceBeanSkeleton
    4. UserServiceBean

    用著用著,第二個問題來了,
    UserServiceBean只有人用,沒人管理,transaction logic, security logic, bean instance pooling logic

    這些不得不考慮的問題浮出水面了。

    OK,我們想到用一個delegate,EJBObject,來進行所有這些logic的管理。client和EJBObject打交道,EJBObj

    ect調用UserServiceBean。

    注意,這個EJBObject也是一個Interface,#6.UserService這個interface正是從它extends而來。并且EJBObje

    ct所管理的這些logic,正是AppServer的一部分。

    現(xiàn)在的流程變?yōu)榱耍?
    EJBObject
    1. UserService.getUserInfo()
    2. UserServiceStub
    3. UserServiceSkeleton
    4. UserServiceImp
    5. UserServiceBean

    這已經和整幅圖里的#6, #7, #8, #9, #10一一對應了。

    現(xiàn)在能滿足我們的需求了嗎?不,第三個問題又來了:
    既然是分布式開發(fā),那么我當然沒理由只用一個Specified Server,我可能需要用到好幾個不同的Server,而

    且EJBObject也需要管理呀

    OK,為了適應你的需要,我們還得加再一個HomeObject,首先它來決定用哪個Server(當然,是由你用JNDI

    String設定的),其次,它來管理EJBObject。

    注意,這個EJBHome也是一個Interface,#1.UserServiceHome這個interface正是從它extends而來。并且EJBHo

    me管理EJBObject的logic,也是AppServer的一部分。

    現(xiàn)在的調用次序是
    1. EJBHome.create()
    2. EJBHomeStub
    3. EJBHomeSkeleton
    4. EJBHomeImp(EJSWrapper)
    5. EJSHome

    得到EJBObject

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

    現(xiàn)在已經完全和流程圖的調用順序一致了。

    //EJB的基礎是RMI IIOP,原理并不是很難,關鍵是實現(xiàn)起來比較繞,一個簡單的功能要用10個(或更多)類來實現(xiàn),但每一個都不是多余的。

    //EJB的這種模式(或說RMI)完全屏蔽了底層的網(wǎng)絡,并很好的實現(xiàn)了對業(yè)務代碼的保護。

    posted on 2007-07-13 11:17 hardson 閱讀(276) 評論(0)  編輯  收藏 所屬分類: ejb


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    統(tǒng)計

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    收藏夾

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 最近免费中文字幕MV在线视频3| 国产亚洲人成在线影院| 日本免费人成网ww555在线| 国产亚洲日韩在线三区| 国产成人无码精品久久久久免费| 亚洲精品无码久久毛片| 一区二区三区在线免费观看视频| 亚洲国产精品尤物yw在线| 国产精品无码免费专区午夜| 亚洲尤码不卡AV麻豆| 永久在线观看免费视频 | 精品国产麻豆免费网站| 亚洲国产片在线观看| 久久久久久99av无码免费网站| 亚洲色大成网站www永久男同| 精品国产麻豆免费网站| 亚洲av无码专区在线观看下载| 国产乱子伦精品免费女| 一级做受视频免费是看美女| 亚洲色偷偷综合亚洲AVYP| 国产人成免费视频网站| 亚洲精品无码成人| 两个人看的www免费| 亚洲国产一区国产亚洲 | 国产AV无码专区亚洲AV琪琪| 亚洲精品国产V片在线观看 | 99久久久精品免费观看国产| 亚洲中文字幕无码av永久| 亚洲电影日韩精品 | 成人免费视频77777| 亚洲AV成人片无码网站| 亚洲综合伊人久久综合| 我的小后妈韩剧在线看免费高清版| 国产亚洲中文日本不卡二区| 国产精品亚洲综合一区| 久久综合国产乱子伦精品免费| 亚洲综合色丁香婷婷六月图片| 亚洲AV中文无码乱人伦| 亚州免费一级毛片| 四虎国产精品成人免费久久 | 亚洲av永久无码精品国产精品|