<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    [摘錄]從代理機(jī)制初探AOP

    摘錄地址:http://www.javaworld.com.tw/jute/post/print?bid=5&id=81236

    1. 從代理機(jī)制初探 AOP? Copy to clipboard

    Posted by: caterpillar

    Posted on: 2004-11-24 11:10

    ?

    ?

    AOP OOP 我覺得 AOP 觀念其實不難,只是很容易被中文混淆, Aspect 在牛津字典中是這么解釋的: particular part or feature of sth being considered.

    ?

    Aspect 中文直譯通常作「方面」,方面在中文通常作「角度」解譯,我們常說「就這個方面來看」,其意是「就這個角度來看」,但在上面的英文解釋中, aspect part 的意義,中文來說是「就這個部份來看」,「我」覺得 Aspect 在中文上應(yīng)是取這個意思。

    ?

    例如一個動作在執(zhí)行過程中的某個「部份」是 AOP 所關(guān)注的,這個部份切入了執(zhí)行過程,但本身不屬于執(zhí)行的最終目的,例如事務(wù)管理,執(zhí)行的目的可能是儲存數(shù)據(jù),但事務(wù)管理切入了這個過程, AOP 關(guān)注于這個「切入面」,希望將其設(shè)計為通用,不介入對象設(shè)計的一個通用組件。

    ?

    AOP 「我」比較接受的一個中文翻譯是「切面導(dǎo)向」,這可以免除「方面」兩字較具「表面」的意義, Aspect 是一個「面」沒錯,但是具有橫切入過程的感覺。。。。。

    ?

    總之,先看看下面的文章,我想應(yīng)該比較了解吧。。。。。

    ?

    ==================================

    ?

    AOP 的全名是 Aspect-oriented Programming Aspect 是程序設(shè)計時一個新的中心, AOP 并不取代 OOP ,兩者各有各的角色,將職責(zé)各自分配自 Object Aspect ,會使得程序中各個組件的角色更為清楚。

    ?

    這邊先不直接探討 AOP ,我們先從一個簡單常見的例子來看看一個議題,這個例子是記錄( log )動作,程序中很常需要為某些動作或事件作下記錄,以便在事后檢視或是作為除錯時的信息,一個最簡單的例子如下:

    import java.util.logging.*;

    ???????????????????????????????????????????????????????????????????????????????

    public class HelloSpeaker {

    ??? private Logger logger = Logger.getLogger(this.getClass().getName());

    ???????????????????????????????????????????????????????????????????????????????

    ?? ?public void hello(String name) {

    ??????? logger.log(Level.INFO, "hello method starts....");

    ???????????????????????????????????????????????????????????????????????????????

    ??????? System.out.println("Hello, " + name);

    ???????????????????????????????????????????????????????????????????????????????

    ??????? logger.log(Level.INFO, "hello method ends....");

    ??? }

    }

    ?

    ?

    HelloSpeaker 在執(zhí)行 hello() 方法時,我們希望能記錄該方法已經(jīng)執(zhí)行及結(jié)束,最簡單的作法就是如上在執(zhí)行的前后加上記錄動作,然而 Logger 介入了 HelloSpeaker 中,記錄這個動作并不屬于 HelloSpeaker ,這使得 HelloSpeaker 的職責(zé)加重。

    ?

    想想如果程序中這種記錄的動作到處都有需求,上面這種寫法勢必造成我們必須復(fù)制記錄動作的程序代碼,使得維護(hù)記錄動作的困難度加大。如果不只有記錄動作,有一些非對象本身職責(zé)的相關(guān)動作也混入了對象之中(例如權(quán)限檢查、事務(wù)管理等等),會使得對象的負(fù)擔(dān)更形加重,甚至混淆了對象的職責(zé),對象本身的職責(zé)所占的程序代碼,或許遠(yuǎn)小于這些與對象職責(zé)不相關(guān)動作的程序代碼。

    ?

    怎么辦,用下面的方法或許好一些,我們先定義一個接口,然后實作該接口:

    public interface IHello {

    ??? public void hello(String name);

    }

    ?

    public class HelloSpeaker implements IHello {

    ??? public void hello(String name) {

    ??????? System.out.println("Hello, " + name);

    ??? }

    }

    ?

    ?

    接下來是重點了,我們實作一個代理對象 HelloProxy

    import java.util.logging.*;

    ???????????????????????????????????????????????????????????????????????????????

    public class HelloProxy implements IHello {

    ??? private Logger logger = Logger.getLogger(this.getClass().getName());

    ??? private IHello helloObject;

    ???????????????????????????????????????????????????????????????????????????????

    ??? public HelloProxy(IHello helloObject) {

    ??????? this.helloObject = helloObject;

    ??? }

    ???????????????????????????????????????????????????????????????????????????????

    ? ?? public void hello(String name) {

    ??????? logger.log(Level.INFO, "hello method starts....");

    ???????????????????????????????????????????????????????????????????????????????

    ??????? helloObject.hello(name);

    ?????????????????????????????????????????????? ?????????????????????????????????

    ??????? logger.log(Level.INFO, "hello method ends....");

    ??? }

    }

    ?

    執(zhí)行時可以如此:

    IHello helloProxy = new HelloProxy(new HelloSpeaker());

    helloProxy.hello("Justin");

    ?

    ?

    代理對象 HelloProxy 將代理真正的 HelloSpeaker 來執(zhí)行 hello() ,并在其前后加上記錄的動作,這使得我們的 HelloSpeaker 在撰寫時不必介入記錄動作, HelloSpeaker 可以專心于它的職責(zé)。

    ?

    這是靜態(tài)代理的基本范例,然而如您所看到的,代理對象的一個接口只服務(wù)于一種類型的對象,而且如果要代理的方法很多,我們勢必要為每個方法進(jìn)行代理,靜態(tài)代理在程序規(guī)模稍大時就必定無法勝任。

    ?

    Java JDK 1.3 之后加入?yún)f(xié)助開發(fā)動態(tài)代理功能的類別,我們不必為特定對象與方法撰寫特定的代理,使用動態(tài)代理,可以使得一個 handler 服務(wù)于各個對象,首先,一個 handler 必須實現(xiàn) java.lang.reflect.InvocationHandler

    import java.util.logging.*;

    import java.lang.reflect.*;

    ????????????????????????????????????????????????????????????????????? ?????????????????

    public class LogHandler implements InvocationHandler {

    ??? private Logger logger = Logger.getLogger(this.getClass().getName());

    ??? private Object delegate;

    ???????????????????????????????????????????????????????????????????????????????? ??????

    ??? public Object bind(Object delegate) {

    ??????? this.delegate = delegate;

    ??????? return Proxy.newProxyInstance(

    ?????????????????????????? delegate.getClass().getClassLoader(),

    ?????????????????????????? delegate.getClass().getInterfaces(),

    ???? ??????????????????????this);

    ??? }

    ??????????????????????????????????????????????????????????????????????????????????????

    ??? public Object invoke(Object proxy, Method method, Object[] args)

    ??????????????? throws Throwable {

    ??????? Object result = null;

    ??????? try {

    ??????????? logger.log(Level.INFO, "method stats..." + method);

    ??????????? result = method.invoke(delegate, args);

    ??????????? logger.log(Level.INFO, "method ends..." + method);

    ??????? } catch (Exception e){

    ??????????? logger.log(Level.INFO, e.toString());

    ??????? }

    ??????? return result;

    ??? }

    }

    ?

    InvocationHandler invoke() 方法會傳入被代理對象的方法名稱與執(zhí)行參數(shù)實際上要執(zhí)行的方法交由 method.invoke() ,并在其前后加上記錄動作, method.invoke() 傳回的對象是實際方法執(zhí)行過后的回傳結(jié)果。

    ?

    動態(tài)代理必須宣告接口,實作該接口,例如:

    public interface IHello {

    ??? public void hello(String name);

    }

    ?

    public class HelloSpeaker implements IHello {

    ??? public void hello(String name) {

    ??????? System.out.println("Hello, " + name);

    ??? }

    }

    ?

    ?

    java.lang.reflect.Proxy newProxyInstance() 依要代理的對象、接口與 handler 產(chǎn)生一個代理對象,我們可以使用下面的方法來執(zhí)行程序:

    LogHandler logHandler? = new LogHandler();

    IHello helloProxy = (IHello) logHandler.bind(new HelloSpeaker());

    helloProxy.hello("Justin");

    ?

    ?

    LogHandler 不在服務(wù)于特定對象與接口,而 HelloSpeaker 也不用插入任何有關(guān)于記錄的動作,它不用意識到記錄動作的存在。

    ?

    講了半天,我們回到 AOP 的議題上,這個例子與 AOP 有何關(guān)系?

    ?

    如上面的例子中示范的, HelloSpeaker 本來必須插入記錄動作,這使得 HelloSpeaker 的職責(zé)加重,并混淆其原來的角色,為此,我們使用代理將記錄的動作提取出來,以厘清記錄動作與 HelloSpeaker 的職責(zé)與角色。

    ?

    在這里,記錄這個動作是我們所關(guān)注的, AOP 中的 Aspect 所指的就是像記錄這類的動作,我們將這些動作(或特定職責(zé))視為關(guān)注的中心,將其設(shè)計為通用、不介入特定對象、職責(zé)清楚的組件,這就是所謂的「 Aspect 導(dǎo)向」(比較好的一個中文翻法是「切面導(dǎo)向」,下一個主題再說明),就如同「對象導(dǎo)向」一樣,每個對象僅代表一個實際的個體,將對象視為關(guān)注的中心,將其設(shè)計為通用、職責(zé)清楚的組件。

    ?

    這邊先以代理機(jī)制作為一個開端初步探討 AOP ,如您所看到的, AOP OOP 并不抵觸,兩者的合作使得程序更為清晰, Object Aspect 職責(zé)不互相混淆,而且都更具重用性,下一個主題我們再來深入 AOP 的一些細(xì)節(jié)。

    ?



    歡迎大家訪問我的個人網(wǎng)站 萌萌的IT人

    posted on 2006-04-24 11:16 見酒就暈 閱讀(119) 評論(0)  編輯  收藏 所屬分類: J2EE文章

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導(dǎo)航

    統(tǒng)計

    常用鏈接

    留言簿(3)

    我參與的團(tuán)隊

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    收藏夾

    BLOG

    FRIENDS

    LIFE

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲日本中文字幕一区二区三区| 99精品在线免费观看| 一级毛片a免费播放王色电影 | 免费看一级高潮毛片| 18禁亚洲深夜福利人口| 亚洲精品天堂无码中文字幕| 亚洲情A成黄在线观看动漫软件| 国产亚洲sss在线播放| 在线观看亚洲AV每日更新无码| 亚洲国产日韩精品| 国产AV无码专区亚洲AV蜜芽| 天堂亚洲免费视频| 中文字幕久无码免费久久| 日韩精品无码免费专区午夜不卡| 大地资源在线资源免费观看 | 一级毛片高清免费播放| 国产国产人免费人成成免视频 | 免费无码AV一区二区| 国产黄片不卡免费| 免费在线看污视频| 国产h肉在线视频免费观看| 和日本免费不卡在线v| 日本免费福利视频| 免费在线观看理论片| 国产亚洲一区二区手机在线观看| 亚洲第一AAAAA片| 亚洲精品国产免费| 亚洲女女女同性video| 日本高清不卡中文字幕免费| 免费观看一区二区三区| 国产大片91精品免费观看不卡| 在线A级毛片无码免费真人 | 皇色在线视频免费网站| 国产精品成人四虎免费视频| 国产亚洲精品无码专区| 老司机亚洲精品影院无码| 亚洲午夜无码久久| 老司机午夜在线视频免费| 国产精品小视频免费无限app| 免费无遮挡无码永久视频 | 一个人看的hd免费视频|