CGLIB動態代理介紹和實例講解

JDK自從1.3版本開始,就引入了動態代理,JDK的動態代理用起來非常簡單,但是它有一個限制,就是使用動態代理的對象必須實現一個或多個接口。如果想代理沒有實現接口的類可以使用CGLIB包。
  CGLIB是一個強大的高性能的代碼生成包。它被許多AOP的框架(例如Spring AOP)使用,爲他們提供方法的interception(攔截)。Hibernate也使用CGLIB來代理單端single-ended(多對一和一對一)關聯。EasyMock通過使用模仿(moke)對象來測試java代碼的包。它們都通過使用CGLIB來爲那些沒有接口的類創建模仿(moke)對象。
  CGLIB包的底層是通過使用一個小而快的字節碼處理框架ASM,來轉換字節碼並生成新的類。不鼓勵直接使用ASM,因爲它要求你必須對JVM內部結構包括class文件的格式和指令集都很熟悉。
下面的圖顯示了和CGLIB包和一些框架和語言的關係。
 
  Spring AOP和Hibernate同時使用JDK的動態代理和CGLIB包。Spring AOP,如果不強制使用CGLIB包,默認情況是使用JDK的動態代理來代理接口。

  CGLIB包對代理那些沒有實現接口的類非常有用。它是通過動態的生成一個子類去覆蓋所要代理類的不是final的方法,並設置好callback,則原有類的每個方法調用就會轉變成調用用戶定義的攔截方法(interceptors)。

  net.sf.cglib.proxy.Callback接口在CGLIB包中是一個很關鍵的接口,所有被net.sf.cglib.proxy.Enhancer類調用的回調(callback)接口都要繼承這個接口。 用net.sf.cglib.proxy.MethodInterceptor接口是最通用的回調(callback)類型,它經常被基於代理的AOP用來實現攔截(intercept)方法的調用。

  net.sf.cglib.proxy.MethodInterceptor能夠滿足任何的攔截(interception )需要,但是某些特殊情況下可能使用過度。爲了簡化和提高性能,CGLIB包提供了一些專門的回調(callback)類型。例如:

net.sf.cglib.proxy.FixedValue 爲提高性能,FixedValue回調對強制某一特別方法返回固定值是有用的。
net.sf.cglib.proxy.NoOp NoOp回調把對方法調用直接委派到這個方法在父類中的實現。
net.sf.cglib.proxy.LazyLoader 當實際的對象需要延遲裝載時,可以使用LazyLoader回調。一旦實際對象被裝載,它將被每一個調用代理對象的方法使用。
net.sf.cglib.proxy.Dispatcher 和LazyLoader不同的是,當代理方法被調用時,裝載對象的方法也總要被調用。
net.sf.cglib.proxy.ProxyRefDispatcher 和Dispatcher不同的是,它可以把代理對象作爲裝載對象方法的一個參數傳遞。

  爲了更好的使用代理,我們可以使用自己定義的MethodInterceptor類型回調(callback)來代替net.sf.cglib.proxy.NoOp回調。當對代理中所有方法的調用時,都會轉向MethodInterceptor類型的攔截(intercept)方法,在攔截方法中再調用底層對象相應的方法。

例一:
public class MyClass {
    public void method() {
        System.out.println("MyClass.method()");
    }
}

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.MethodInterceptor;
 
public class Test {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyClass.class);
        enhancer.setCallback( new MethodInterceptorImpl() );
        MyClass my = (MyClass)enhancer.create();
        my.method();
    }
 
    private static class MethodInterceptorImpl implements MethodInterceptor {
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println(method);
            proxy.invokeSuper(obj, args);
            return null;
        }
    }
}

/*
javac -cp .;cglib-2.1.3.jar;asm-1.5.3.jar *.java
pause
java -cp .;cglib-2.1.3.jar;asm-1.5.3.jar  Test
pause
*/

example source code and related libs
發佈了48 篇原創文章 · 獲贊 7 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章