• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    EJB 最佳實踐:動態委派

    發布: 2007-6-06 17:21 | 作者: 網絡轉載 | 來源: 網絡 | 查看: 26次 | 進入軟件測試論壇討論

    領測軟件測試網
    EJB 最佳實踐:動態委派
    用 Java 反射構建更通用的業務委派

    級別:中級

    Brett McLaughlinbrett@oreilly.com
    作家兼編輯,O'Reilly and Associates
    2003 年 3 月

    盡管業務委派類確實給您的企業 Java 設計帶來了激動人心的新靈活性,但為您應用程序中的每個會話 bean 都編碼一個業務委派還是太麻煩了。在 EJB 最佳實踐系列的這篇文章里,Brett McLaughlin 向您展示了如何創建業務委派類的更通用的版本:動態委派。

    上一篇技巧文章中,我們討論了如何用業務委派類(請不要與業務接口(Business Interface)模式相混淆)來訪問您的 EJB 組件。通過在客戶機代碼和 EJB 代碼之間插入業務委派類,我們可以將應用程序的 Web 層與 EJB 語義和業務邏輯隔離開來。

    研究這類設計的一種方法是看它有多通用。先從一個應用程序入手,該應用程序中的業務邏輯和技術函數是緊密地交織在一起的,我們已經逐步分離出應用程序的不同層,并使用不同的技術來降低它們的相互依賴。在這樣做時,您應該會發現:應用程序底層結構越通用,則隨著時間的推移,它就會越健壯且可維護性越好。

    在這篇技巧文章中,我們將繼續使用通用設計的思想。我們將從研究當前業務委派實現的限制入手,然后我將向您展示如何通過創建更通用的(因而不那么呆板)業務委派類實現來克服這些限制。

    業務委派類:復習
    回顧一下我們上個月討論的 Library bean 接口的業務委派類。

    LibraryDelegate 類的大部分代碼只是復制了原始 Library bean 的方法。LibraryDelegate 添加了 init()、destroy() 和構造器方法,然后用這些方法將任務委派給 Library bean。在這樣做時,委派充當 Web 層和企業 bean 之間的緩沖區。這里是原始 bean 的業務接口。

    方法的繁殖
    除非您考慮到多個會話 bean 有 10 個、20 個或更多方法,否則這種方法的問題并不明顯。實際上,找到擁有 50 個或更多方法的會話 bean 并不罕見!因為 bean 的業務接口必須包括該 bean 的所有方法,所以業務委派類也將這樣做。那會使代碼過于龐大,并很容易出錯。

    您的輸入是否太快了?
    在使用 EJB 組件時,我們經?缭竭h程接口、業務接口、實現類和現在的業務委派類來復制許多方法。我們中的許多人喜歡在編輯器窗口和 IDE 之間剪切和粘貼方法,而不是手工輸入它們,但請注意:按 Option+V 或 Control+V 會象手工輸入方法一樣容易出錯 — 您添加的方法越多,出錯的可能性就越大。通過仔細檢驗您是否正確地輸入了方法,以及是否按預期剪切和粘貼了它們,最終可以使您避免許多麻煩。

    除了龐大的代碼之外,我們還必須考慮變化因素。因為 Delegate 類必須復制 bean 的所有方法,并且隨著時間推移,bean 不可避免地會發生變化,您會發現需要花費很多時間來將新的方法添加到 Delegate,更別提重新編譯了,有可能還要測試新代碼。

    就其本身而言,這看起來似乎不是很嚴重的問題。但假如我們開始使用業務委派類來從技術基礎結構(在本文是指 EJB 組件)中抽象業務和表示邏輯呢。如果更改遠程接口需要對業務委派進行更改,那么,實際上,我們的業務委派仍然與底層組件聯系在一起。

    我們需要更好的方法,您說是不是。確實有更好的方法。

    動態委派
    解決方案是使用動態委派,而它又使用 Java 反射(reflection)。您可以使委派動態地調用目標 EJB 組件的遠程接口上的方法(通過 Java Reflection API),而不必將每個業務方法硬編碼到委派中。這樣允許徹底消除來自遠程接口的耦合,因為,為 bean 的業務或遠程接口添加方法時不需要在業務委派中進行相應更改。使用動態委派還使得更改您的技術基礎結構更為容易。從遠程接口和 EJB 技術遷移到另一種技術(如 Java Data Objects,JDO)只需要更改委派的 init() 方法。所有其它方法調用將繼續通過 bean 的接口進行委派,并且可以繼續使用無需進一步更改。清單 1 顯示了 Library 業務委派的動態版本:

    清單 1. Library bean 的業務委派
    
    package com.ibm.library;
    
    import java.lang.reflect.Method;
    import java.lang.reflect.InvocationTargetException;
    import java.rmi.RemoteException;
    import java.util.HashMap;
    import java.util.Map;
    import javax.ejb.CreateException;
    import javax.naming.NamingException;
    
    public class LibraryDelegate implements ILibrary {
      private ILibrary library;
      private Map availableMethods;
    
      public LibraryDelegate() {
        init();
      }
    
          public void init() {
            // Look up and obtain our session bean
            try {
              LibraryHome libraryHome =
                (LibraryHome)EJBHomeFactory.getInstance().lookup(
                  "java:comp/env/ejb/LibraryHome", LibraryHome.class);
              library = libraryHome.create();
    
              // Get the methods available for use in proxying
              availableMethods = new HashMap();
              Method[] methods = ILibrary.class.getMethods();
              for (int i=0; i<methods.length; i++) {
                availableMethods.put(methods[i].getName(),
                  methods[i]);
              }
            } catch (NamingException e) {
              throw new RuntimeException(e);
            } catch (CreateException e) {
              throw new RuntimeException(e);
            } catch (RemoteException e) {
              throw new RuntimeException(e);
            }
          }
    
          // All the hard-coded methods are removed
          public Object
            invoke(Object proxy, Method method, Object[] args)
            throws Throwable{
    
            try {
              // See if this is init() or destroy()
              if (method.getName().equals("init")) {
                init();
                return null;
              } else if (method.getName().equals("destroy")) {
                destroy();
                return null;
              } else {
                Method method =
                  (Method)availableMethods.get(method.getName());
    
                // See if we found anything
                if (method != null) {
                  return method.invoke(library, args);
                } else {
                  throw new
                    NoSuchMethodException("The Library does not " +
                    "support the  " + method.getName() +" method.");
                }
              }
            } catch (InvocationTargetException e) {
              // We don't support throwing RuntimeExceptions from EJBs
              // directly
              if (e.getTargetException() instanceof RemoteException) {
                throw new RuntimeException(e);
                } else {
                  throw e.getTargetException();
                }
              }
            }
    
            public void destroy() {
              // In this case, do nothing
            }
          }
    

    動態委派出色地解決了委派、bean 及其業務接口之間的耦合問題。但是,它并不是完美的解決方案,也不會總是最好的解決方案。雖然您從這種方法中獲得了極大的靈活性,但也付出了性能代價。Java 反射并不十分快,因此在調用 invoke() 和獲得結果之間,您會感到一些延時。前一篇技巧文章中展示的靜態業務委派類是更快的解決方案,但它使您的業務層和技術層的耦合程度比您所希望的要高。因此,在權衡這兩個選擇時,選擇哪一個要根據設計或性能而定。當應用程序的設計比整體性能更重要時,動態委派是更好的選擇。當性能是更重要的因素時,業務委派是更好的選擇。

    您可能會發現自己正在將動態委派用于內部網應用程序,在內部網中,所有機器都在本地網絡上,并且您會經常添加或更改功能。對于電子商業和面向顧客的應用程序,原始的業務委派可能是更好的選擇。在這兩種情況下,您現在都應該對業務委派及其工作原理有了更好的理解。好好玩,玩得開心點,我們網上再見!

     

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/

    TAG: 最佳 ejb 委派


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備2023014753號-2
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>