1. 程式人生 > >代理模式之Cglib代理

代理模式之Cglib代理

Cglib代理,也叫做子類代理。在記憶體中構建一個子類物件從而實現對目標物件功能的擴充套件。

JDK的動態代理有一個限制,就是使用動態代理的物件必須實現一個或多個介面。如果想代理沒有實現介面的類,就可以使用CGLIB實現。

  CGLIB是一個強大的高效能的程式碼生成包,它可以在執行期擴充套件Java類與實現Java介面。它廣泛的被許多AOP的框架使用,例如Spring AOP和dynaop,為他們提供方法的interception(攔截)。

 CGLIB包的底層是通過使用一個小而快的位元組碼處理框架ASM

,來轉換位元組碼並生成新的類。不鼓勵直接使用ASM,因為它要求你必須對JVM內部結構包括class檔案的格式和指令集都很熟悉。

Cglib子類代理:

         1) 需要引入cglib – jar檔案, 但是spring的核心包中已經包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。

         2)引入功能包後,就可以在記憶體中動態構建子類

         3)代理的類不能為final, 否則報錯。

         4) 目標物件的方法如果為final/static, 那麼就不會被攔截,即不會執行目標物件額外的業務方法。

在Spring的AOP程式設計中,

         如果加入容器的目標物件有實現介面,用JDK代理;

         如果目標物件沒有實現介面,用Cglib代理;

package loaderman.c_cglib;

import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; /** * 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; } }
package loaderman.c_cglib;

/**
 * 目標物件
 *
 */
public class UserDao {

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

}
package loaderman.c_cglib;

public class App {

    public static void main(String[] args) {
        // 目標物件
        UserDao target = new UserDao();
        // class loaderman.c_cglib.UserDao
        System.out.println(target.getClass());

        // 代理物件
        UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();
        // UserDao子類:class loaderman.c_cglib.UserDao$$EnhancerByCGLIB$$25d4aeab
        System.out.println(proxy.getClass());

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