Sung in Blog

                     一些技術(shù)文章 & 一些生活雜碎
          實(shí)現(xiàn)EJB

          如果你選擇使用EJB,Spring能在EJB實(shí)現(xiàn)和客戶端訪問(wèn)EJB兩方面都提供很大的好處。

          對(duì)業(yè)務(wù)邏輯進(jìn)行重構(gòu),把它從EJB facades中取出到POJO已經(jīng)得到了廣泛的認(rèn)同。(不講別的,這使得業(yè)務(wù)邏輯更容易單元測(cè)試,因?yàn)镋JB嚴(yán)重依賴于容器而難于分離測(cè)試。)Spring為session bean和message driver bean提供了方便的超類,使得通過(guò)自動(dòng)載入基于包含在EJB Jar文件中的XML文檔BeanFactory讓這變得很容易。

          這意味著stateless session EJB可以這么獲得和使用所需對(duì)象:

          代碼:

          import org.springframework.ejb.support.AbstractStatelessSessionBean;

          public class MyEJB extends AbstractStatelessSessionBean
                   implements MyBusinessInterface {
             private MyPOJO myPOJO;

             protected void onEjbCreate() {
                this.myPOJO = getBeanFactory().getBean("myPOJO");
             }

             public void myBusinessMethod() {
                this.myPOJO.invokeMethod();
             }
          }

          假定MyPOJO是一個(gè)接口,它的實(shí)現(xiàn)類——以及任何它需要的配置,注入基本的屬性和更多的合作者——在XML bean factory 定義中隱藏。

          我們通過(guò)在ejb-jar.xmldeployment descriptor中名為ejb/BeanFactoryPath的環(huán)境變量定義告訴Spring去哪兒裝載XML文檔。如下:

          代碼:

          <session>
             <ejb-name>myComponent</ejb-name>
             <local-home>com.test.ejb.myEjbBeanLocalHome</local-home>
             <local>com.mycom.MyComponentLocal</local>
             <ejb-class>com.mycom.MyComponentEJB</ejb-class>
             <session-type>Stateless</session-type>
             <transaction-type>Container</transaction-type>

             <env-entry>
                <env-entry-name>ejb/BeanFactoryPath</env-entry-name>
                <env-entry-type>java.lang.String</env-entry-type>
                <env-entry-value>/myComponent-ejb-beans.xml</env-entry-value></env-entry>
             </env-entry>
          </session>

          myComponent-ejb-beans.xml 文件將會(huì)從classpath裝載:在本例中,是EJB Jar文件的根目錄。每個(gè)EJB都能指定自己的XML文檔,因而這個(gè)機(jī)制能在每個(gè)EJB Jar文件中使用多次。

          Spring 的超類實(shí)現(xiàn)了EJB中諸如setSessionContext()和ejbCreate()的生命周期管理的方法,讓應(yīng)用程序開發(fā)者只需選擇是否實(shí)現(xiàn)Spring的onEjbCreate()方法。
           
           
          使用EJB

          Spring還讓實(shí)現(xiàn)EJB變得更加容易。許多EJB程序使用Service Locator和Business Delegate模式。這些比在客戶代碼中遍布JNDI查找強(qiáng)多了,但是它們常見的實(shí)現(xiàn)方式有顯著的缺點(diǎn),例如:


            使用EJB的典型代碼依賴Service Locator或者Business Delegate singletons,使得測(cè)試難于進(jìn)行。

            在Service Locator模式?jīng)]有使用Business Delegate的情況下,程序代碼還要在EJB home中調(diào)用create()方法,并且處理可能導(dǎo)致的異常。因而仍然綁定在EJB API身上,忍受著EJB 編程模型的復(fù)雜度。

            實(shí)現(xiàn)Business Delegate模式通常導(dǎo)致顯著的代碼重復(fù),其中我們必須編寫大量?jī)H僅是調(diào)用EJB同等方法的方法。

          基于這些和其他原因,傳統(tǒng)的EJB訪問(wèn),如在Sun Adventure Builder和OTN J2EE Virtual Shopping Mall中展示的那樣,會(huì)降低生產(chǎn)率并且?guī)?lái)顯著的復(fù)雜度。

          Spring通過(guò)引入codeless business delegate前進(jìn)了一步。有了Spring,你不再需要再編寫另一個(gè)Service Locator,另一個(gè)JNDI查找,或者在硬編碼的Business Delegate中重復(fù)代碼,除非你肯定這增加了價(jià)值。

          例如,假定我們有使用local EJB的web controller。我們將遵循最佳實(shí)踐,使用EJB Business Methods Interface模式,EJB的local interface extend非EJB專有的業(yè)務(wù)方法接口。(這么做的主要的一個(gè)原因是確保在本地接口和bean實(shí)現(xiàn)類中方法簽名的自動(dòng)同步。)讓我們調(diào)用這個(gè)業(yè)務(wù)方法接口MyComponent。當(dāng)然我們還需要實(shí)現(xiàn)local home接口并且提供實(shí)現(xiàn)SessionBean和MyComponent業(yè)務(wù)方法的bean的實(shí)現(xiàn)類。

          用了Spring EJB 訪問(wèn),我們把我們的web層controller和EJB實(shí)現(xiàn)掛接上所需要進(jìn)行的Java編碼僅僅是在我們的controller中暴露一個(gè)類型MyComponent的setter方法。這將如下保存作為實(shí)例變量的引用:

          代碼:

          private MyComponent myComponent;

          public void setMyComponent(MyComponent myComponent) {
             this.myComponent = myComponent;
          }

          我們隨后在任何業(yè)務(wù)方法中使用這個(gè)實(shí)例變量。

          Spring自動(dòng)完稱剩下的工作,通過(guò)像這樣的XML bean定義。LocalStatelessSessionProxyFactoryBean是一個(gè)可以用于任何EJB的通用factory bean。它創(chuàng)建的對(duì)象能夠自動(dòng)被Spring轉(zhuǎn)型為MyComponent類型。

          代碼:

          <bean id="myComponent"
          class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">

             <property name="jndiName"><value>myComponent</value></property>
             <property name="businessInterface"><value>com.mycom.MyComponent</value></property>
          </bean>

          <bean id="myController"
             class = "com.mycom.myController"
          >
             <property name="myComponent"><ref bean="myComponent"/></property>
          </bean>

          在幕后有許多魔法般的事情發(fā)生,Spring AOP framework的殷勤,雖然不強(qiáng)迫你使用AOP的概念享受這些結(jié)果。“myComponent”bean定義為EJB創(chuàng)建一個(gè)代理,它實(shí)現(xiàn)了業(yè)務(wù)方法的接口。EJB local home在啟動(dòng)的時(shí)候被緩存,因而只需要一次JNDI查找。每次EJB被調(diào)用的時(shí)候,代理調(diào)用local EJB中的create()方法并且調(diào)用EJB中對(duì)應(yīng)的業(yè)務(wù)方法。

          myController bean定義為這個(gè)代理設(shè)置controller類的myController屬性。

          這個(gè)EJB訪問(wèn)機(jī)制極大簡(jiǎn)化了應(yīng)用程序的代碼:


            Web層的代碼不依賴于EJB的使用。如果你想要使用POJO,mock object或者其他test stub替代EJB引用,我們可以簡(jiǎn)單地改動(dòng)一下myComponent bean定義而不影響一行Java代碼

            我們還不需要寫一行JNDI查找或者其他EJB plumbing code。

          在實(shí)際程序中的性能測(cè)試和經(jīng)驗(yàn)標(biāo)明這種方法(包括對(duì)目標(biāo)EJB的反射調(diào)用)的性能影響是很小的,在典型的應(yīng)用中檢測(cè)不出。記住無(wú)論如何我們都不希望使用fine-grained的EJB調(diào)用,因?yàn)闀?huì)有有關(guān)應(yīng)用服務(wù)器上的EJB的底層架構(gòu)方面的代價(jià)。

          我們可以把相同方法應(yīng)用于遠(yuǎn)程EJB,通過(guò)類似org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean factory bean的方法。然而我們無(wú)法隱藏遠(yuǎn)程EJB的業(yè)務(wù)方法接口中的RemoteException。
          posted on 2005-10-26 16:08 Sung 閱讀(274) 評(píng)論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 含山县| 辰溪县| 霍邱县| 当阳市| 旺苍县| 庆阳市| 合川市| 嵊泗县| 古浪县| 卢龙县| 灵宝市| 弥勒县| 昌平区| 武城县| 青龙| 临城县| 平湖市| 嘉黎县| 香港 | 墨玉县| 塘沽区| 平遥县| 七台河市| 东明县| 休宁县| 综艺| 河津市| 日土县| 垫江县| 新邵县| 鸡东县| 抚顺市| 和林格尔县| 和平县| 慈溪市| 措美县| 调兵山市| 扶绥县| 乌审旗| 横山县| 玉环县|