在Spring中提供了兩個代理工廠Bean來代理EJB的訪問:
- LocalStatelessSessionProxyFactoryBean - 用來訪問本地EJB(EJB和它的客戶端在同一個容器中)。
- SimpleRemoteStatelessSessionProxyFactoryBean - 用來訪問遠程EJB(EJB和它的客戶端在獨立的容器中)。
例如:
<bean id="businessComponent" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean" lazy-init=”true”>
<property name="jndiName">
<value>ejb/location.business.comp</value>
</property>
<property name="businessInterface">
<value>com.test.LocationBusinessComponent</value>
</property>
</bean>
SimpleRemoteStatelessSessionProxyFactoryBean是個代理工廠Bean類,該Bean通過jndiName屬性就可以查找到這個EJB的home接口。在容器啟動的時 候,SimpleRemoteStatelessSessionProxyFactoryBean通過該JNDI來查找EJB 的遠程Home接口,接著它會把這個接口緩存起來,這樣每次在businessComponent上的方法被調用時,代理就會調用遠程接口上的create()方法來取得這個EJB的引用,而不需要再進行同樣的JNDI查找了。businessInterface屬性等同與在其他遠程服務代理工廠Bean中使用的serviceInterface,它表示這個EJB服務依附在LocationBusinessComponent接口上。
關於這個聲明,一件需要注意的事情就是<Bean>元素的lazy-init屬性。在《spring in action》中提到:當任何一個EJB代理工廠Bean在ApplicationContext中使用時,這一 點是相當重要的。這是因為在Spring配置文件被裝載進來的時候,ApplicationContext風格的Bean工廠預先實例化了單實例的 Bean。這通常是一件好事,但它可能會導致EJB代理工廠Bean在EJB被綁定到名字服務之前,試圖查找EJB的home接口。把lazy-init 設置為true,可確保這個EJB在裝載時不會試圖查找home接口,直到它首次被使用為止,這將會留有足夠的時間來把EJB綁定到名稱服務上。
經過嘗試,lazy-init屬性並不奏效,我的代碼場景是通過一個init的servlet去載入一個引用了businessComponent的bean,設置了lazy-init屬性之後,spring容器依然會在載入時初始化businessComponent。通過查閱spring的api後發現,最好的解決辦法是設置lookupHomeOnStartup屬性,將該屬性為false,spring將會在第一次訪問ejb時才去獲取home接口。測試之後,該配置起作用了,更改後的配置如下:
<bean id="businessComponent" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean">
<property name="jndiName">
<value>ejb/location.business.comp</value>
</property>
<property name="businessInterface">
<value> com.test.LocationBusinessComponent</value>
</property>
<property name="lookupHomeOnStartup">
<value>false</value>
</property>
</bean>
更詳細的信息可參考關於SimpleRemoteStatelessSessionProxyFactoryBean 的api:http://static.springsource.org/spring/docs/1.2.x/api/org/springframework/ejb/access/SimpleRemoteStatelessSessionProxyFactoryBean.html