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

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

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

    [摘錄]從代理機制初探AOP

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

    1. 從代理機制初探 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 在中文上應是取這個意思。

    ?

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

    ?

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

    ?

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

    ?

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

    ?

    AOP 的全名是 Aspect-oriented Programming Aspect 是程序設計時一個新的中心, AOP 并不取代 OOP ,兩者各有各的角色,將職責各自分配自 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 在執行 hello() 方法時,我們希望能記錄該方法已經執行及結束,最簡單的作法就是如上在執行的前后加上記錄動作,然而 Logger 介入了 HelloSpeaker 中,記錄這個動作并不屬于 HelloSpeaker ,這使得 HelloSpeaker 的職責加重。

    ?

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

    ?

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

    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....");

    ??? }

    }

    ?

    執行時可以如此:

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

    helloProxy.hello("Justin");

    ?

    ?

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

    ?

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

    ?

    Java JDK 1.3 之后加入協助開發動態代理功能的類別,我們不必為特定對象與方法撰寫特定的代理,使用動態代理,可以使得一個 handler 服務于各個對象,首先,一個 handler 必須實現 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() 方法會傳入被代理對象的方法名稱與執行參數實際上要執行的方法交由 method.invoke() ,并在其前后加上記錄動作, method.invoke() 傳回的對象是實際方法執行過后的回傳結果。

    ?

    動態代理必須宣告接口,實作該接口,例如:

    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 產生一個代理對象,我們可以使用下面的方法來執行程序:

    LogHandler logHandler? = new LogHandler();

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

    helloProxy.hello("Justin");

    ?

    ?

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

    ?

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

    ?

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

    ?

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

    ?

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

    ?



    歡迎大家訪問我的個人網站 萌萌的IT人

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

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

    導航

    統計

    常用鏈接

    留言簿(3)

    我參與的團隊

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    收藏夾

    BLOG

    FRIENDS

    LIFE

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产日本亚洲一区二区三区| 久久九九亚洲精品| 亚洲人精品亚洲人成在线| 久久久久久国产精品免费无码| 亚洲中文字幕日产乱码高清app| 曰批免费视频播放免费| 国产传媒在线观看视频免费观看| 亚洲乱色伦图片区小说| 国产精品99久久免费| 污网站免费在线观看| 亚洲日韩人妻第一页| 久草免费福利在线| 亚洲AV人人澡人人爽人人夜夜| 无码一区二区三区免费| 亚洲欧洲春色校园另类小说| 免费可以在线看A∨网站| 亚洲成熟丰满熟妇高潮XXXXX| 成人免费视频国产| 一区二区三区AV高清免费波多| 亚洲日本va在线视频观看| 人妻免费一区二区三区最新| 亚洲色成人网一二三区| 成人人观看的免费毛片| 日亚毛片免费乱码不卡一区| 国产亚洲A∨片在线观看| 一级毛片免费视频| 亚洲国产成人久久综合| 国产AⅤ无码专区亚洲AV| 1000部无遮挡拍拍拍免费视频观看| 亚洲午夜在线一区| 四虎AV永久在线精品免费观看| 久久免费国产精品| 亚洲国产成人精品久久| 亚洲AV蜜桃永久无码精品| 国产精品偷伦视频观看免费| 日本亚洲免费无线码| 亚洲精品乱码久久久久久蜜桃不卡 | aaa毛片免费观看| 亚洲国产成+人+综合| 亚洲色婷婷综合开心网| 在线精品一卡乱码免费|