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

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

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

    AOP編程入門(轉載)

    Aspect Oriented Programming(AOP),面向切面編程,是一個比較熱門的話題。AOP主要實現的目的是針對業務處理過程中的切面進行提取,它所面對的是處理過程中的某個步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。比如我們最常見的就是日志記錄了,舉個例子,我們現在提供一個服務查詢學生信息的,但是我們希望記錄有誰進行了這個查詢。如果按照傳統的OOP的實現的話,那我們實現了一個查詢學生信息的服務接口(StudentInfoService)和其實現類(StudentInfoServiceImpl.java),同時為了要進行記錄的話,那我們在實現類(StudentInfoServiceImpl.java)中要添加其實現記錄的過程。這樣的話,假如我們要實現的服務有多個呢?那就要在每個實現的類都添加這些記錄過程。這樣做的話就會有點繁瑣,而且每個實現類都與記錄服務日志的行為緊耦合,違反了面向對象的規則。那么怎樣才能把記錄服務的行為與業務處理過程中分離出來呢?看起來好像就是查詢學生的服務自己在進行,但是背后日志記錄對這些行為進行記錄,但是查詢學生的服務不知道存在這些記錄過程,這就是我們要討論AOP的目的所在。AOP的編程,好像就是把我們在某個方面的功能提出來與一批對象進行隔離,這樣與一批對象之間降低了耦合性,可以就某個功能進行編程。
    ????我們直接從代碼入手吧,要實現以上的目標,我們可以使用一個動態代理類(Proxy),通過攔截一個對象的行為并添加我們需要的功能來完成。Java中的java.lang.reflect.Proxy類和java.lang.reflect.InvocationHandler接口為我們實現動態代理類提供了一個方案,但是該方案針對的對象要實現某些接口;如果針對的目的是類的話,cglib為我們提供了另外一個實現方案。等下會說明兩者的區別。
    一、接口的實現方案:
    1)首先編寫我們的業務接口(StudentInfoService.java):
    public interface StudentInfoService{
    ?void findInfo(String studentName);
    }
    ???? 及其實現類(StudentInfoServiceImpl.java):
    public class StudentInfoServiceImpl implements StudentInfoService{
    ?public void findInfo(String name){
    ??System.out.println("你目前輸入的名字是:"+name);
    ?}
    }
    2)現在我們需要一個日志功能,在findInfo行為之前執行并記錄其行為,那么我們就首先要攔截該行為。在實際執行的過程中用一個代理類來替我們完成。Java中為我們提供了實現動態代理類的方案:

    1'處理攔截目的的類(MyHandler.java)
    import org.apache.log4j.Logger;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.Method;

    public class MyHandler implements InvocationHandler{
    ?private Object proxyObj;
    ?private static Logger log=Logger.getLogger(MyHandler.class);
    ?
    ?public Object bind(Object obj){
    ??this.proxyObj=obj;
    ??return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
    ?}
    ?
    ?public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
    ??Object result=null;
    ??try{
    ???//請在這里插入代碼,在方法前調用
    ???log.info("調用log日志方法"+method.getName());
    ???result=method.invoke(proxyObj,args); //原方法
    ???//請在這里插入代碼,方法后調用
    ??}catch(Exception e){
    ???e.printStackTrace();
    ??}
    ??return result;
    ?}
    }
    2'我們實現一個工廠,為了方便我們使用該攔截類(AOPFactory.java):
    public class AOPFactory{
    ?private static Object getClassInstance(String clzName){
    ??Object obj=null;
    ??try{
    ???Class cls=Class.forName(clzName);
    ???obj=(Object)cls.newInstance();
    ??}catch(ClassNotFoundException cnfe){
    ???System.out.println("ClassNotFoundException:"+cnfe.getMessage());
    ??}catch(Exception e){
    ???e.printStackTrace();
    ??}
    ??return obj;
    ?}
    ?
    ?public static Object getAOPProxyedObject(String clzName){
    ??Object proxy=null;
    ??MyHandler handler=new MyHandler();
    ??Object obj=getClassInstance(clzName);
    ??if(obj!=null) {
    ???proxy=handler.bind(obj);
    ??}else{
    ???System.out.println("Can't get the proxyobj");
    ???//throw
    ??}
    ??return proxy;
    ?}
    }

    3)基本的攔截與其工廠我們都實現了,現在測試(ClientTest.java):
    public class ClientTest{
    ?public static void main(String[] args){
    ??StudentInfoService studentInfo=(StudentInfoService)AOPFactory.getAOPProxyedObject("StudentInfoServiceImpl");
    ??studentInfo.findInfo("阿飛");
    ?}
    }
    輸出結果(看你的log4j設置):
    [INFO]調用log日志方法findInfo
    你目前輸入的名字是:阿飛
    ???? 這樣我們需要的效果就出來了,業務處理自己在進行,但是我們實現了日志功能,而業務處理(StudentInfoService)根本不知道存在該行為的。但是Java中提供的動態代理類的實現是針對實現了某些接口的類,如果沒有實現接口的話,不能創建代理類,看以上部分:
    return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
    看到了沒有?obj.getClass().getInterfaces()要求實現了某些接口。以下提供哪些沒有實現接口的實現方案:

    二、子類的實現方案。
    ????? 首先,請上網下CGLib的包,http://sourceforge.net/project/showfiles.php?group_id=56933?。設置好classpath路徑,CGLib與java標準庫提供的實現方案不同,cglib主要是基于實現類(如StudentInfoServiceImpl.java)擴展一個子類來實現。與Dynamic Proxy中的Proxy和InvocationHandler相對應,net.sf.cglib.proxy.Enhancer和MethodInterceptor在CGLib中負責完成代理對象創建和方法截獲處理,產生的是目標類的子類而不是通過接口來實現方法攔截的,Enhancer主要是用于構造動態代理子類來實現攔截,MethodInterceptor(擴展了Callback接口)主要用于實現around advice(AOP中的概念):
    ???? 1)我們的業務處理(StudentInfoServiceImpl.java):
    public class StudentInfoServiceImpl{
    ?public void findInfo(String name){
    ??System.out.println("你目前輸入的名字是:"+name);
    ?}
    }
    ???? 2)實行一個工具來處理日志功能(AOPInstrumenter.java):
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodProxy;
    import java.lang.reflect.Method;
    import org.apache.log4j.Logger;

    public class AOPInstrumenter implements MethodInterceptor{
    ?private Logger log=Logger.getLogger(AOPInstrumenter.class);
    ?private Enhancer enhancer=new Enhancer();
    ?
    ?public Object getInstrumentedClass(Class clz){
    ??enhancer.setSuperclass(clz);
    ??enhancer.setCallback(this);
    ??return enhancer.create();
    ?}
    ?
    ?public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) throws Throwable{
    ??log.info("調用日志方法"+method.getName());
    ??Object result=proxy.invokeSuper(o,args);
    ??return result;
    ?}
    ?
    }
    ???? 3)我們來測試一下(AOPTest.java):
    public class AOPTest{
    ?public static void main(String[] args){
    ??AOPInstrumenter instrumenter=new AOPInstrumenter();
    ??StudentInfoServiceImpl studentInfo=(StudentInfoServiceImpl)instrumenter.getInstrumentedClass(StudentInfoServiceImpl.class);
    ??studentInfo.findInfo("阿飛");
    ?}
    }
    ?? 輸出結果與以上相同。
    ?CGLib中為實現以上目的,主要提供的類
    1)Enhancer:setCallback(Callback) ,setSuperclass(Class) ,create()返回動態子類Object
    2)MethodInterceptor必須實現的接口:intercept(Object,Method,Object[],MethodProxy)返回的是原方法調用的結果。和Proxy原理一樣。

    三、以上的兩個簡單實現AOP的方案都為你準備好了,你可以自己編寫測試一下,以下簡單介紹一下AOP的基本概念:
    1)aspect(切面):實現了cross-cutting功能,是針對切面的模塊。最常見的是logging模塊,這樣,程序按功能被分為好幾層,如果按傳統的繼承的話,商業模型繼承日志模塊的話根本沒有什么意義,而通過創建一個logging切面就可以使用AOP來實現相同的功能了。
    2)jointpoint(連接點):連接點是切面插入應用程序的地方,該點能被方法調用,而且也會被拋出意外。連接點是應用程序提供給切面插入的地方,可以添加新的方法。比如以上我們的切點可以認為是findInfo(String)方法。
    3)advice(處理邏輯):advice是我們切面功能的實現,它通知程序新的行為。如在logging里,logging advice包括logging的實現代碼,比如像寫日志到一個文件中。advice在jointpoint處插入到應用程序中。以上我們在MyHandler.java中實現了advice的功能
    4)pointcut(切點):pointcut可以控制你把哪些advice應用于jointpoint上去,通常你使用pointcuts通過正則表達式來把明顯的名字和模式進行匹配應用。決定了那個jointpoint會獲得通知。
    5)introduction:允許添加新的方法和屬性到類中。
    6)target(目標類):是指那些將使用advice的類,一般是指獨立的那些商務模型。比如以上的StudentInfoServiceImpl.

    7)proxy(代理類):使用了proxy的模式。是指應用了advice的對象,看起來和target對象很相似。
    8)weaving(插入):是指應用aspects到一個target對象創建proxy對象的過程:complie time,classload time,runtime



    posted on 2006-06-09 15:33 nbt 閱讀(232) 評論(0)  編輯  收藏 所屬分類: Spring框架

    <2006年6月>
    28293031123
    45678910
    11121314151617
    18192021222324
    2526272829301
    2345678

    導航

    統計

    常用鏈接

    留言簿(3)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    相冊

    收藏夾

    Java技術網站

    友情鏈接

    國內一些開源網站

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 黄色网站软件app在线观看免费| 亚洲av乱码中文一区二区三区| 国产日韩AV免费无码一区二区三区| 免费观看毛片视频| 亚洲午夜成人精品无码色欲| 国产三级在线观看免费| 亚洲三级在线观看| 在线免费观看国产视频| 国产亚洲精彩视频| 亚洲精品国产自在久久 | 亚洲午夜免费视频| 亚洲欧洲日韩国产综合在线二区| 久久这里只精品99re免费| 亚洲性天天干天天摸| 亚洲成人免费在线观看| 亚洲AV成人影视在线观看| 国产精品另类激情久久久免费| 免费一区二区三区在线视频| 国产亚洲色婷婷久久99精品91| 水蜜桃视频在线观看免费播放高清| 亚洲成年轻人电影网站www| 四虎永久在线观看免费网站网址 | 男女超爽视频免费播放| 久久亚洲av无码精品浪潮| 一区二区三区福利视频免费观看| 亚洲网址在线观看你懂的| 大地资源免费更新在线播放| 美女免费视频一区二区三区| 亚洲国产三级在线观看| 免费人成网站在线观看10分钟| 在线观看亚洲电影| 亚洲高清国产拍精品26U| 免费下载成人电影| eeuss草民免费| 亚洲va精品中文字幕| 亚洲第一区在线观看| 99久久免费观看| 国产无限免费观看黄网站| 亚洲视频在线观看一区| 免费人成视频在线| a级毛片无码免费真人久久|