【黑馬程式設計師濟南中心】代理模式-Cglib代理

canghaigudu發表於2018-04-22

【黑馬程式設計師濟南中心】代理模式-Cglib代理
今天和大家聊一條java中代理模式的第三種設計模式-Cglib模式。前兩天我們聊了靜態代理和動態代理,但是大家有沒有發現這兩種代理模式都是要求目標物件是實現一個介面的目標物件,但是有時候目標物件只是一個單獨的物件,並沒有實現任何的介面。而這時候我們就可以使用Cglib模式,它可以使用以目標物件子類的方式類實現代理。
Cglib代理的概念:也叫作子類代理,它是在記憶體中構建一個子類物件從而實現對目標物件功能的擴充套件
JDK的動態代理有一個限制,就是使用動態代理的物件必須實現一個或多個介面,如果想代理沒有實現介面的類,就可以使用Cglib實現.
Cglib是一個強大的高效能的程式碼生成包,它可以在執行期擴充套件java類與實現java介面.它廣泛的被許多AOP的框架使用,例如Spring AOP和synaop,為他們提供方法的interception(攔截)
Cglib包的底層是通過使用一個小而塊的位元組碼處理框架ASM來轉換位元組碼並生成新的類.不鼓勵直接使用ASM,因為它要求你必須對JVM內部結構包括class檔案的格式和指令集都很熟悉.
Cglib子類代理實現方法:
1.需要引入cglib的jar檔案,但是Spring的核心包中已經包括了Cglib功能,所以直接引入pring-core-3.2.5.jar即可.
2.引入功能包後,就可以在記憶體中動態構建子類
3.代理的類不能為final,否則報錯
4.目標物件的方法如果為final/static,那麼就不會被攔截,即不會執行目標物件額外的業務方法.
下邊給大家舉個使用Cglib代理的例子:
目標物件類:UserDao.java:
/**
* 目標物件,沒有實現任何介面
*/
public class UserDao {

public void save() {
    System.out.println("----已經儲存資料!----");
}

}

Cglib代理工廠:ProxyFactory.java:
/**
* Cglib子類代理工廠
* 對UserDao在記憶體中動態構建一個子類物件
*/
public class ProxyFactory implements MethodInterceptor{
//維護目標物件
private Object target;

public ProxyFactory(Object target) {
    this.target = target;
}

//給目標物件建立一個代理物件
public Object getProxyInstance(){
    //1.工具類
    Enhancer en = new Enhancer();
    //2.設定父類
    en.setSuperclass(target.getClass());
    //3.設定回撥函式
    en.setCallback(this);
    //4.建立子類(代理物件)
    return en.create();

}

@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    System.out.println("開始事務...");

    //執行目標物件的方法
    Object returnValue = method.invoke(target, args);

    System.out.println("提交事務...");

    return returnValue;
}

}
測試類:
/**
* 測試類
*/
public class App {

@Test
public void test(){
    //目標物件
    UserDao target = new UserDao();

    //代理物件
    UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();

    //執行代理物件的方法
    proxy.save();
}

}

在Spring的AOP程式設計中,如果加入容器的目標物件有實現介面,用JDK代理,如果目標物件沒有實現介面,用Cglib代理。
一般Cglib代理在Spring框架中應用,所以小夥伴們可以把它當做瞭解內容看一看。

相關文章