在這篇技巧文章中,我們將研究一些最常用的 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() 是絕對有可能的(從而一次建立兩個上下文),但只有首次調用該方法時才會發生此類錯誤。因為問題至多隻會發生一次,所以同步是不必要的,實際上,同步引入的複雜性比它所解決的複雜性更多。