EJB 遠程調用的本質是 RMI(Remote Method Invocation),但經過容器層層包裝,形成雙重 RMI 迴路。本文從手寫 RMI 原型入手,逐層剖析 WebSphere 與 WebLogic 的 10 類別生成機制與調用鏈路,還原 EJB 分布式調用的真實面貌。
RMI 實現跨 JVM 呼叫:Client 端 Stub 封裝參數透過 Socket 發送,Server 端 Skeleton 解封並呼叫真實物件,再將結果返回。關鍵點:
Person person = new Person_Stub())。Serializable,採值傳遞語義。一個 Stateless Session Bean 經 WSAD 編譯生成 10 個 Class:
| 序號 | 類別 | 角色 |
|---|---|---|
| 1 | UserServiceHome | Home 介面(開發者編寫) |
| 2 | UserService | Remote 介面(開發者編寫) |
| 3 | UserServiceBean | Bean 實作(開發者編寫) |
| 4 | _UserServiceHome_Stub | Home Stub(Client 端動態載入) |
| 5 | _EJSRemoteStatelessUserServiceHome_..._Tie | Home Skeleton(Server 端,Tie=CORBA 術語) |
| 6 | EJSRemoteStatelessUserServiceHome_... | Home Server 端實作 |
| 7 | EJSStatelessUserServiceHomeBean_... | Home Bean 包裝器,負責建立 Remote Stub |
| 8 | _UserService_Stub | Remote Stub(Client 端動態載入) |
| 9 | _EJSRemoteStatelessUserService_..._Tie | Remote Skeleton(Server 端) |
| 10 | EJSRemoteStatelessUserService_... | Remote Server 端實作,委派給 Bean |
_UserServiceHome_Stub(偽裝為 Home 介面)。home.create() → Stub 發送 "create" 字串 → Skeleton 接收分派 → Home Server 實作 create() → 委派 HomeBean 包裝器 createWrapper() → 返回 _UserService_Stub。EJSWrapper 無建立 Stub 能力,必須委派繼承 EJSHome 的 HomeBean。object.getUserInfo() → Remote Stub 發送方法名與參數 → Remote Skeleton 分派 → Remote Server 實作 getUserInfo() → 容器 preInvoke() → 終於呼叫 UserServiceBean.getUserInfo()。WebLogic 差異在於:
create() 經 Home Skeleton/Server → 返回 Remote Stub → 業務調用經 Remote Skeleton/Server → 委派 Bean 實作。作者以演進視角還原設計必然性:
總計 10 類,各司其職,無一冗餘。EJB 基於 RMI-IIOP,完美屏蔽網絡細節,保護業務代碼純粹性。