Spring常被視為EJB輕量級替代品,但現實場景中:
Spring通過代理模式封裝EJB訪問細節,消除樣板代碼(JNDI查找、Home創建、異常處理),實現依賴注入式EJB消費。
// 傳統方式:充斥樣板代碼
Context ctx = new InitialContext();
Object ref = ctx.lookup("ejb/MyBean");
MyHome home = (MyHome) PortableRemoteObject.narrow(ref, MyHome.class);
MyRemote bean = home.create(); // 拋出CreateException、RemoteException
bean.doBusiness(); // 業務調用
引入Service Locator和Business Delegate模式雖緩解,但引入新問題:難以單元測試、仍耦合EJB API、產生大量委托方法樣板代碼。
<bean id="myComponent" class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<property name="jndiName" value="ejb/MyBean" />
<property name="businessInterface" value="com.mycom.MyComponent" />
</bean>
<bean id="myController" class="com.mycom.MyController">
<property name="myComponent" ref="myComponent" /> <!-- 注入代理 -->
</bean>
關鍵機制:
MyComponent,控制器僅依賴接口home.create()→業務方法→移除實例(SLSB無狀態)LocalSlsbInvokerInterceptor處理創建/調用/異常轉換配置類似,但關鍵差異在異常處理:
RemoteException(受檢異常),客戶端被迫捕獲RemoteAccessException(繼承RuntimeException,非受檢)提倡「EJB只做容器服務(事務/安全/遠程),業務邏輯放POJO」:
// 業務接口
public interface MyComponent { void myMethod(); }
// POJO實現(純Java,無EJB依賴)
public class MyComponentImpl implements MyComponent {
public void myMethod() { /* 核心業務邏輯 */ }
}
// 無狀態Session Bean:薄包裝層
public class MyComponentEJB extends AbstractStatelessSessionBean implements MyComponent {
private MyComponent myComp;
protected void onEjbCreate() throws CreateException {
// 從BeanFactory獲取POJO實例
myComp = (MyComponent) getBeanFactory().getBean("myComponent");
}
public void myMethod() { myComp.myMethod(); } // 委托調用
}
| Bean類型 | Spring基類 | 關鍵模板方法 |
|---|---|---|
| 無狀態Session Bean | AbstractStatelessSessionBean | onEjbCreate()、setSessionContext() |
| 有狀態Session Bean | AbstractStatefulSessionBean | ejbPassivate()/ejbActivate()管理BeanFactory序列化 |
| 消息驅動Bean | AbstractMessageDrivenBean / AbstractJmsMessageDrivenBean | onEjbCreate()、setMessageDrivenContext() |