1. 程式人生 > >實現一個Cglib代理Demo

實現一個Cglib代理Demo

Cglib動態代理採用的是建立目標類的子類的方式。優點:不用實現額外介面,只操作我們關心類,高效能。

package jesse.test;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

class Father{
    public void sayHello(){
        System.out.println("this is father");
    }
}

interface Person{
    void speak();
    void walk();
}

class Student extends Father implements Person{
    public void study(){
        System.out.println("i am student.");
    }
    
    @Override
    public void speak() {
        System.out.println("i am student ,i can speak");
    }

    @Override
    public void walk() {
        System.out.println("i am student ,i can walk");        
    }
}

class MyMethodInterceptor implements MethodInterceptor{
    @Override
    public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {
        System.out.println("Before: "+ method);
        Object object = proxy.invokeSuper(obj, arg);
        System.out.println("After: "+method);
        return object;
    }
    
}

public class MyCglibProxy {
    public static void main(String[] args) {
        //可以指定 CGLIB 將動態生成的代理類儲存至指定的磁碟路徑下
        //System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"本地磁碟路徑");
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Student.class);
        enhancer.setCallback(new MyMethodInterceptor());
        Student student = (Student)enhancer.create();
        student.sayHello();
        student.speak();
        student.walk();
        student.study();
    }
    
}
/**
 * 就是隻能為介面中的方法完成代理,而委託類自己的方法或者父類中的方法都不可能被代理。
 * CGLIB 應運而生,它是一個高效能的,底層基於 ASM 框架的一個程式碼生成框架,它完美的解決了 JDK 版本的
 * 動態代理只能為介面方法代理的單一性不足問題
 * 
 * Student 是我們需要代理的委託型別,結果生成的代理類就直接繼承了委託類。
 * 這一個小設計就完美的解決了 JDK 動態代理那個單一代理的缺陷,繼承了委託類,就可以反射出委託類介面中的所有方法,
 * 父類中的所有方法,自身定義的所有方法,完成這些方法的代理就完成了對委託類所有方法的代理。
 * 
 * 說明:cglib生成代理是通過位元組碼生成的子類作為代理類,因此不能對private final方法代理;
 * 
 * 比較:
 * CGLib動態代理建立代理例項速度慢,但是執行速度快;JDK動態代理建立例項速度快,但是執行速度慢。如果例項是單例的,
 * 推薦使用CGLib方式動態代理,反之則使用JDK方式進行動態代理。Spring的例項預設是單例,所以這時候使用CGLib效能高。 
 * 
 */

  

<!-- cglib -->
<dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.2.5</version>
</dependency>