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

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

用 Java 反射構(gòu)建更通用的業(yè)務(wù)委派

2019-11-18 15:18:54
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  盡管業(yè)務(wù)委派類(lèi)確實(shí)給您的企業(yè) java 設(shè)計(jì)帶來(lái)了激動(dòng)人心的新靈活性,但為您應(yīng)用程序中的每個(gè)會(huì)話(huà) bean 都編碼一個(gè)業(yè)務(wù)委派還是太麻煩了。在 EJB 最佳實(shí)踐系列的這篇文章里,Brett McLaughlin 向您展示了如何創(chuàng)建業(yè)務(wù)委派類(lèi)的更通用的版本:動(dòng)態(tài)委派。
在上一篇技巧文章中,我們討論了如何用業(yè)務(wù)委派類(lèi)(請(qǐng)不要與業(yè)務(wù)接口(Business Interface)模式相混淆)來(lái)訪(fǎng)問(wèn)您的 EJB 組件。通過(guò)在客戶(hù)機(jī)代碼和 EJB 代碼之間插入業(yè)務(wù)委派類(lèi),我們可以將應(yīng)用程序的 Web 層與 EJB 語(yǔ)義和業(yè)務(wù)邏輯隔離開(kāi)來(lái)。

研究這類(lèi)設(shè)計(jì)的一種方法是看它有多通用。先從一個(gè)應(yīng)用程序入手,該應(yīng)用程序中的業(yè)務(wù)邏輯和技術(shù)函數(shù)是緊密地交織在一起的,我們已經(jīng)逐步分離出應(yīng)用程序的不同層,并使用不同的技術(shù)來(lái)降低它們的相互依靠。在這樣做時(shí),您應(yīng)該會(huì)發(fā)現(xiàn):應(yīng)用程序底層結(jié)構(gòu)越通用,則隨著時(shí)間的推移,它就會(huì)越健壯且可維護(hù)性越好。

在這篇技巧文章中,我們將繼續(xù)使用通用設(shè)計(jì)的思想。我們將從研究當(dāng)前業(yè)務(wù)委派實(shí)現(xiàn)的限制入手,然后我將向您展示如何通過(guò)創(chuàng)建更通用的(因而不那么呆板)業(yè)務(wù)委派類(lèi)實(shí)現(xiàn)來(lái)克服這些限制。

業(yè)務(wù)委派類(lèi):復(fù)習(xí)
回顧一下我們上個(gè)月討論的 Library bean 接口的業(yè)務(wù)委派類(lèi)。

LibraryDelegate 類(lèi)的大部分代碼只是復(fù)制了原始 Library bean 的方法。LibraryDelegate 添加了 init()、destroy() 和構(gòu)造器方法,然后用這些方法將任務(wù)委派給 Library bean。在這樣做時(shí),委派充當(dāng) Web 層和企業(yè) bean 之間的緩沖區(qū)。這里是原始 bean 的業(yè)務(wù)接口。

方法的繁殖
除非您考慮到多個(gè)會(huì)話(huà) bean 有 10 個(gè)、20 個(gè)或更多方法,否則這種方法的問(wèn)題并不明顯。實(shí)際上,找到擁有 50 個(gè)或更多方法的會(huì)話(huà) bean 并不罕見(jiàn)!因?yàn)?bean 的業(yè)務(wù)接口必須包括該 bean 的所有方法,所以業(yè)務(wù)委派類(lèi)也將這樣做。那會(huì)使代碼過(guò)于龐大,并很輕易出錯(cuò)。

您的輸入是否太快了?
在使用 EJB 組件時(shí),我們經(jīng)常跨越遠(yuǎn)程接口、業(yè)務(wù)接口、實(shí)現(xiàn)類(lèi)和現(xiàn)在的業(yè)務(wù)委派類(lèi)來(lái)復(fù)制許多方法。我們中的許多人喜歡在編輯器窗口和 IDE 之間剪切和粘貼方法,而不是手工輸入它們,但請(qǐng)注重:按 Option+V 或 Control+V 會(huì)象手工輸入方法一樣輕易出錯(cuò) ? 您添加的方法越多,出錯(cuò)的可能性就越大。通過(guò)仔細(xì)檢驗(yàn)?zāi)欠裾_地輸入了方法,以及是否按預(yù)期剪切和粘貼了它們,最終可以使您避免許多麻煩。
除了龐大的代碼之外,我們還必須考慮變化因素。因?yàn)?Delegate 類(lèi)必須復(fù)制 bean 的所有方法,并且隨著時(shí)間推移,bean 不可避免地會(huì)發(fā)生變化,您會(huì)發(fā)現(xiàn)需要花費(fèi)很多時(shí)間來(lái)將新的方法添加到 Delegate,更別提重新編譯了,有可能還要測(cè)試新代碼。

就其本身而言,這看起來(lái)似乎不是很?chē)?yán)重的問(wèn)題。但假如我們開(kāi)始使用業(yè)務(wù)委派類(lèi)來(lái)從技術(shù)基礎(chǔ)結(jié)構(gòu)(在本文是指 EJB 組件)中抽象業(yè)務(wù)和表示邏輯呢。假如更改遠(yuǎn)程接口需要對(duì)業(yè)務(wù)委派進(jìn)行更改,那么,實(shí)際上,我們的業(yè)務(wù)委派仍然與底層組件聯(lián)系在一起。

我們需要更好的方法,您說(shuō)是不是。確實(shí)有更好的方法。

動(dòng)態(tài)委派
解決方案是使用動(dòng)態(tài)委派,而它又使用 Java 反射(reflection)。您可以使委派動(dòng)態(tài)地調(diào)用目標(biāo) EJB 組件的遠(yuǎn)程接口上的方法(通過(guò) Java Reflection API),而不必將每個(gè)業(yè)務(wù)方法硬編碼到委派中。這樣答應(yīng)徹底消除來(lái)自遠(yuǎn)程接口的耦合,因?yàn)?,?bean 的業(yè)務(wù)或遠(yuǎn)程接口添加方法時(shí)不需要在業(yè)務(wù)委派中進(jìn)行相應(yīng)更改。使用動(dòng)態(tài)委派還使得更改您的技術(shù)基礎(chǔ)結(jié)構(gòu)更為輕易。從遠(yuǎn)程接口和 EJB 技術(shù)遷移到另一種技術(shù)(如 Java Data Objects,JDO)只需要更改委派的 init() 方法。所有其它方法調(diào)用將繼續(xù)通過(guò) bean 的接口進(jìn)行委派,并且可以繼續(xù)使用無(wú)需進(jìn)一步更改。清單 1 顯示了 Library 業(yè)務(wù)委派的動(dòng)態(tài)版本:

清單 1. Library bean 的業(yè)務(wù)委派
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
}
}



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

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 合阳县| 广宁县| 濉溪县| 蚌埠市| 汤阴县| 北海市| 清徐县| 勐海县| 乳山市| 榕江县| 北川| 榆中县| 苍溪县| 民乐县| 墨脱县| 丹寨县| 金湖县| 阿合奇县| 阜新| 东安县| 丰顺县| 祥云县| 丹江口市| 平和县| 江津市| 泽库县| 牙克石市| 镇原县| 新民市| 塔河县| 凌海市| 永泰县| 益阳市| 剑川县| 揭东县| 克山县| 惠水县| 丰镇市| 芦溪县| 苍溪县| 资源县|