Java的面向AOP編程

來源:互聯網
上載者:User

標籤:aop   cglib   spring   事件   編程   

一、 引言

AOP(Aspect-Oriented Programming,面向切面的編程),是一種新型的編程範式,主張關注軟體流程中的一個切面,將同樣功能的代碼整合打包在一起,降低系統的耦合性,增強其擴充性。

傳統的軟體設計,往往採取事件驅動模型帶來類似的效果,通過在可能的事件切入點插入事件回呼函數,將對應位置插入外置代碼。

函數式編程,也有類似的解決方案,通過函數傳遞,將對應位置的擴充上新的功能。

Java作為一門嚴謹的傳統式開發語言,以安全性和可靠性為第一標準,語言並沒有過多的新特性支援,Java8僅支援到lambda運算式,為了使Java具有更強大的編程模型,Spring等架構使用gclib庫實現了面向切面的編程模型。

二、 CGLIB 和 ASM

CGLIB 是一個強大的,高效能,高品質的Code產生類庫,被廣泛的用作動態代理技術。CGLIB 包的底層是通過使用一個小而快的位元組碼處理架構ASM,來轉換位元組碼並產生新的類,新的位元組碼可以被Java虛擬機器直接載入運行。

其實動態代理並不是CGLIB的專利,早在JDK1.3版起,就引入了動態代理庫,Spring AOP 編程時就可以進行選擇,使用JDK提供的動態代理庫,或者是引入CGLIB庫。

下面舉一個執行個體,來說明一些如何使用CGLIB庫,將我們本來應該正常執行的函數調用,進行截斷操作。

package com.abs.testcglib;public class Service {    String name;    public Service(String name) {        this.name = name;    }    public void sayHello() {        System.out.println("Hello "+name);    }}

首先,我們建立一個服務類,其中有一個sayHello() 方法,我們希望將這個方法截斷,以添加其餘組件的一些處理功能,例如持久化組件希望在此添加一條記錄一類的功能。

package com.abs.testcglib;public class Main {    public static void main(String[] args) {        Service s = new Service("Sxf");        s.sayHello();    }}

在Main函數中調用一下,可以看的Hello Sxf 的輸出。

但我們怎麼截斷呢?首先就要建立一個代理類,所謂代理,就是你讓這個代理類,代你調用這個類的函數。

建立一個代理類:

package com.abs.testcglib;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class CglibProxy implements MethodInterceptor {    @Override    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {        System.out.println("方法名:"+method.getName());        Service a = (Service) o;        a.name = "Wah";        System.out.println("哈哈,我要改名");        Object result = methodProxy.invokeSuper(o, args);        return result;    }}

這個代理類的功能,就是將傳統的Java直接的函數調用,包上一次外殼,因為Java本身的函數調用是系統完成的,很難由你大段他,但代理類不同,你可以明確的看的調用了哪個函數,並且可以根據這點,輕鬆的在函數調用前後,插入你希望插入的代碼。

public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy)
這個函數大概是整個代理調用中最關鍵的一個函數了,o這個參數表示了該函數所在的對象,args是調用的參數,Method則是反射到的方法。最後一個則是代理的執行個體。
我們對函數的打斷功能,則都在這個函數裡實現。

當然,由於是通過代理實現,對象的構建也有所不同,所以我們自己寫一個static函數作為建構函式使用。

package com.abs.testcglib;import net.sf.cglib.proxy.Enhancer;public class Service {    String name;    public Service(String name) {        this.name = name;    }    public void sayHello() {        System.out.println("Hello "+name);    }    public static Service getProxyInstance(CglibProxy myProxy, String name) {        Enhancer en = new Enhancer();        // 設定父類和回調        en.setSuperclass(Service.class);        en.setCallback(myProxy);        // 調用其建構函式,需要傳入對應的Class列表和參數Object列表        return (Service) en.create(new Class[] {String.class}, new Object[] {name});    }}

而Main函數中也應該這樣使用該對象:

package com.abs.testcglib;public class Main {    public static void main(String[] args) {        Service s = new Service("Sxf");        s.sayHello();        Service s2 = Service.getProxyInstance(new CglibProxy(), "Sxf");        s2.sayHello();    }}

我們發現,兩種方式建立出的對象,使用上幾乎一樣,唯一不同的就是建構函式時,我們進行了部分修改,其餘部分,不影響我們的對象正常傳遞,儲存等功能。

最終效果:

三、 Spring AOP 的實現

其實看來剛才CGLIB的實現,再看著名的Spring架構,就會發現兩者的實現方式幾乎完全一樣,只不過Spring架構多增加了一些概念和功能。

下面我們寫一個Target 類,這是一個被代理的目標對象,其中有一個execute()方法,現在使用 AOPexecute()方法做日誌輸出。在執行execute()方法前,做日誌輸出。

public class Target {    public void execute(String name){        System.out.println("executeMethod is here" + name);    }}

通知可以攔截目標對象的 execute()方法,並執行日誌輸出。建立通知的代碼如下:

public class LoggerExecute implements MethodInterceptor {    public Object invoke(MethodInvocation arg0) throws Throwable {        before();        arg0.proceed();        return null;    }    private void before() {        System.out.println("executeMethod is exe!");    }}

建立代理的方法也幾乎一樣:

public static void main(String[] args) {    //建立目標對象    Target target = new Target();    //建立代理    ProxyFactory di=new ProxyFactory();    di.addAdvice(new BeforeExecute());    di.setTarget(target);    Target proxy=(Target)di.getProxy();    //代理執行execute()方法    proxy.execute(" ni hao");}

當然Spring的切入點和其設定檔關聯十分緊密,用Spring架構能夠將系統的更多固定參數丟到設定檔中去,或者直接使用註解也可以。

Java的面向AOP編程

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.