国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

EJB 最佳實踐:工業強度的 JNDI 優化

2019-11-18 12:38:16
字體:
來源:轉載
供稿:網友

  Brett McLaughlin 在這篇 EJB 最佳實踐專欄文章中研究了 JNDI 查找,它是幾乎所有的 EJB 交互中不可或缺并且常見的部分。遺憾的是,JNDI 操作幾乎總是需要性能開銷。在本技巧文章中,Brett 向您展示了 home 接口工廠是如何降低您 EJB 應用程序中 JNDI 查找開銷的。
  每種 EJB 組件(會話、實體和消息驅動的)都有 home 接口。home 接口是 bean 的操作基礎;一旦您找到它,就可以使用該 bean 的功能。EJB 應用程序依靠 JNDI 查找來訪問其 bean 的 home 接口。因為 EJB 應用程序往往運行多個 bean,并且因為許多組件中經常使用 JNDI 查找,所以應用程序大部分性能開銷都花費在這些查找上。
  
  在這篇技巧文章中,我們將研究一些最常用的 JNDI 優化。非凡地,我們將向您展示如何將高速緩存和通用助手類組合使用,以創建針對 JNDI 開銷的工廠風格的解決方案。
  
  減少上下文實例
  清單 1 顯示了一段典型的 EJB 代碼,它需要多次 JNDI 查找。請花一點時間研究代碼,然后我們將對它進行優化以獲得更佳性能。
  
  清單 1. 典型的 EJB 查找
  public boolean buyItems(PaymentInfo paymentInfo, String storeName,
  List items) {
   // Load up the initial context
   Context ctx = new InitialContext();
  
   // Look up a bean's home interface
   Object obj = ctx.lookup("java:comp/env/ejb/PurchaseHome");
   PurchaseHome purchaseHome =
   (PurchaseHome)PortableRemoteObject.narrow(obj, PurchaseHome.class);
   Purchase purchase = purchaseHome.create(paymentInfo);
  
   // Work on the bean
   for (Iterator i = items.iterator(); i.hasNext(); ) {
   purchase.addItem((Item)i.next());
   }
  
   // Look up another bean
   Object obj = ctx.lookup("java:comp/env/ejb/InventoryHome");
   InventoryHome inventoryHome =
   (InventoryHome)PortableRemoteObject.narrow(obj, InventoryHome.class);
   Inventory inventory = inventoryHome.findByStoreName(storeName);
  
   // Work on the bean
   for (Iterator i = items.iterator(); i.hasNext(); )
   inventory.markAsSold((Item)i.next());
   }
  
   // Do some other stuff
  }
  
  
  
  
  盡管這個示例多少有點刻意,但它確實揭示了使用 JNDI 時的一些最明顯的問題。對于初學者,您應該問問自己,新建 InitialContext 對象是否必需。很可能在應用程序代碼的其它地方已經裝入了這個上下文,而我們又在這里創建了一個新的。高速緩存 InitialContext 實例會立即促使性能提高,如清單 2 所示:
  
  清單 2. 高速緩存 InitialContext 實例
  public static Context getInitialContext() {
   if (initialContext == null) {
   initialContext = new InitialContext();
   }
  
   return initialContext;
  }
  
  
  
  
  通過對 getInitialContext() 使用助手類,而不是為每個操作都實例化一個新的 InitialContext,我們將遍布在應用程序中的上下文數量減少為一個。
  
  哦 — 線程化會怎么樣?
  假如您對此處提出的解決方案的線程化感到擔心,那大可不必。兩個線程同時進行 getInitialContext() 是絕對有可能的(從而一次創建兩個上下文),但只有首次調用該方法時才會發生此類錯誤。因為問題至多只會發生一次,所以同步是不必要的,實際上,同步引入的復雜性比它所解決的復雜性更多。
  
  優化查找
  高速緩存上下文實例這個步驟的方向是正確的,但僅這樣做,還不足以完成優化。我們每次調用 lookup() 方法時都會執行一次新查找,并返回 bean 的 home 接口的新實例。至少,JNDI 查找通常是這樣編碼的。但假如每個 bean 都只有一個 home 接口,并在多個組件上共享這個接口,這樣不是更好嗎?
  
  我們可以高速緩存每個單獨的 bean 引用,而不是反復查找 PurchaseHome 或 InventoryHome 的 home 接口;這是一種解決方案。但我們真正想要的是一種更通用的機制:在 EJB 應用程序中高速緩存 home 接口。
  
  答案是創建通用助手類,它既可以為應用程序中的每個 bean 獲取初始上下文,又可以為它們查找 home 接口。此外,這個類還應該能夠為各種應用程序組件治理每個 bean 的上下文。清單 3 中所示的通用助手類將充當 EJB home 接口的工廠:
  
  清單 3. EJB home 接口工廠
  package com.ibm.ejb;
  
  import java.util.Map;
  import javax.ejb.EJBHome;
  import javax.naming.Context;
  import javax.naming.InitialContext;
  import javax.naming.NamingException;
  
  public class EJBHomeFactory {
  
   PRivate static EJBHomeFactory;
  
   private Map homeInterfaces;
   private Context context;
  
   // This is private, and can't be instantiated directly
   private EJBHomeFactory() throws NamingException {
   homeInterfaces = new HashMap();
  
   // Get the context for caching purposes
   context = new InitialContext();
  
   /**
   * In non-J2EE applications, you might need to load up
   * a properties file and get this context manually. I've
   * kept this simple for demonstration purposes.
   */
   }
  
   public static EJBHomeFactory getInstance() throws NamingException {
   // Not completely thread-safe, but good enough
   // (see note in article)
   if (instance == null) {
   instance = new EJBHomeFactory();
   }
   return instance;
   }
  
   public EJBHome lookup(String jndiName, Class homeInterfaceClass)
   throws NamingException {
  
   // See if we already have this interface cached
   EJBHome homeInterface = (EJBHome)homeInterfaces.get(homeClass);
  
   // If not, look up with the supplied JNDI name
   if (homeInterface == null) {
   Object obj = context.lookup(jndiName);
   homeInterface =
   (EJBHome)PortableRemoteObject.narrow(obj, homeInterfaceClass);
  
   // If this is a new ref, save for caching purposes
   homeInterfaces.put(homeInterfaceClass, homeInterface);
   }
   return homeInterface;
   }
  }
  
  
  
  
  EJBHomeFactory 類內幕
  home 接口工廠的要害在 homeInterfaces 映射中。該映射存儲了供使用的每個 bean 的 home 接口;這樣,home 接口實例可以反復使用。您還應注重,映射中的要害并不是傳遞到 lookup() 方法的 JNDI 名稱。將同一 home 接口綁定到不同 JNDI 名稱是很常見的,但這樣做會在您的映射中產生副本。通過依靠類本身,您就可以確保最終不會為同一個 bean 創建多個 home 接口。
  
  將新的 home 接口工廠類插入清單 1 的原始代碼,這樣將會產生優化的 EJB 查找,如清單 4 所示:
  
  清單 4. 改進的 EJB 查找
  public boolean buyItems(PaymentInfo paymentInfo, String storeName,
  List items) {
  
   EJBHomeFactory f = EJBHomeFactory.getInstance();
  
   PurchaseHome purchaseHome =
   (PurchaseHome)f.lookup("java:comp/env/ejb/PurchaseHome",
   PurchaseHome.class);
   Purchase purchase = purchaseHome.create(paymentInfo);
  
   // Work on the bean
   for (Iterator i = items.iterator(); i.hasNext(); ) {
   purchase.addItem((Item)i.next());
   }
  
   InventoryHome inventoryHome =
   (InventoryHome)f.lookup("java:comp/env/ejb/InventoryHome",
   InventoryHome.class);
   Inventory inventory = inventoryHome.findByStoreName(storeName);
  
   // Work on the bean
   for (Iterator i = items.iterator(); i.hasNext(); ) {
   inventory.markAsSold((Item)i.next());
   }
  
   // Do some other stuff
  }
  
  
  
  
  隨著時間的推進,除了更清楚之外(至少按我的觀點),以上工廠優化的 EJB 查找將執行得更快。您第一次使用這個新類時,將花費所有正常查找開銷(假定應用程序的其它部分沒有付出過這種開銷),但將來的所有

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 曲靖市| 汶上县| 抚宁县| 建瓯市| 丁青县| 布尔津县| 临海市| 松江区| 万全县| 赣榆县| 吴桥县| 蓬溪县| 密云县| 卢湾区| 色达县| 乌兰县| 靖边县| 黄龙县| 新丰县| 孙吴县| 凉山| 周口市| 阿拉善盟| 泾阳县| 德兴市| 东源县| 共和县| 阿鲁科尔沁旗| 拉萨市| 应用必备| 太谷县| 安泽县| 房产| 镇雄县| 称多县| 通化县| 太和县| 苏尼特右旗| 祁连县| 交口县| 鄢陵县|