動態代理,動態代理設計模式 ,JDK動態代理,cglib動態代理

一:在看此篇代碼示例前,先看靜態代理, java

連接地址:http://my.oschina.net/dyyweb/blog/656760    (代碼示例) 程序員

二:JDK動態代理 web

動態代理與靜態代理類對照的是動態代理類,動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。動態代理類不只簡化了編程工做,並且提升了軟件系統的可擴展性,由於Java 反射機制能夠生成任意類型的動態代理類。java.lang.reflect 包中的Proxy類和InvocationHandler 接口提供了生成動態代理類的能力
編程

/**
 *定義一種類型的女人,王婆和潘金蓮都屬於這個類型的女人
 */
public interface KindWoman {
    //這種女人能作什麼事情呢?
    public void makeEyesWithMan();//拋媚眼

    public void happyWithMan();//和男人那個....
}



/**
 * 潘金蓮
 */
public class PanJinLian  implements KindWoman{
    @Override
    public void happyWithMan() {
        System.out.println("潘金蓮和男人在作那個...");

    }

    @Override
    public void makeEyesWithMan() {
        System.out.println("潘金蓮拋媚眼...");

    }
}



/**
 * 那咱們再考慮一下,水滸裏面還有沒有這類型的女人?
 * 有,盧俊義的老婆賈氏(就是和那個管家苟合的那個),這個名字起的:「賈氏」,那咱們也讓王婆作她的代理:
 */
public class JiaShi implements KindWoman{
    @Override
    public void happyWithMan() {
        System.out.println("賈氏和男人在作那個...");

    }

    @Override
    public void makeEyesWithMan() {
        System.out.println("賈氏拋媚眼...");

    }
}



/**
 * jdk動態代理
 *
 * 王婆變身動態代理
 */
public class WangPoProxy implements InvocationHandler{

    private Object target;

    //綁定委託對象並返回一個代理類
    public Object createProxyTarget(Object target){
        this.target = target;
        //取得代理對象,要綁定接口(這是一個缺陷,cglib彌補了這一缺陷)
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.err.println("+++++++++開始切入++++++++++++");

        Object result=method.invoke(target, args);   //執行方法

        System.err.println("+++++++++++結束切入++++++++++");

        return result;
    }
}



public class XiMenQiang {

    public static void main(String[] args) {
        //王婆出廠
        WangPoProxy wangPo =  new WangPoProxy();
        //潘金蓮出場
        PanJinLian panJinLian  = new PanJinLian();
        //告王婆代理潘金蓮苟且之事
        KindWoman woman = (KindWoman) wangPo.createProxyTarget(panJinLian);

        //而後西門慶說,我要和潘金蓮Happy,而後王婆就安排了西門慶丟筷子哪齣戲:
        woman.makeEyesWithMan();
        //看到沒有表面是王婆在作,其實爽的是潘金蓮
        woman.happyWithMan();


        //西門慶勾引賈氏
        JiaShi jiaShi = new JiaShi();
        woman = (KindWoman) wangPo.createProxyTarget(jiaShi);
        woman.makeEyesWithMan();
        woman.happyWithMan();
    }
}



JDK動態代理中包含一個類和一個接口: 
InvocationHandler接口: 
public interface InvocationHandler { 
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 

參數說明: 
Object proxy:指被代理的對象。 
Method method:要調用的方法 
Object[] args:方法調用時所須要的參數  app

能夠將InvocationHandler接口的子類想象成一個代理的最終操做類,替換掉ProxySubject。  ide

Proxy類: 
Proxy類是專門完成代理的操做類,能夠經過此類爲一個或多個接口動態地生成實現類,此類提供了以下的操做方法: 
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, 
InvocationHandler h) 
                               throws IllegalArgumentException 
參數說明: 
ClassLoader loader:類加載器 
Class<?>[] interfaces:獲得所有的接口 
InvocationHandler h:獲得InvocationHandler接口的子類實例  this

Ps:類加載器 
在Proxy類中的newProxyInstance()方法中須要一個ClassLoader類的實例,ClassLoader實際上對應的是類加載器,在Java中主要有一下三種類加載器; 
Booststrap ClassLoader:此加載器採用C++編寫,通常開發中是看不到的; 
Extendsion ClassLoader:用來進行擴展類的加載,通常對應的是jre\lib\ext目錄中的類; 
AppClassLoader:(默認)加載classpath指定的類,是最常使用的是一種加載器。  spa

三:

可是,JDK的動態代理依靠接口實現,若是有些類並無實現接口,則不能使用JDK代理,這就要使用cglib動態代理了。  .net

Cglib動態代理 
JDK的動態代理機制只能代理實現了接口的類,而不能實現接口的類就不能實現JDK的動態代理,cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現加強,但由於採用的是繼承,因此不能對final修飾的類進行代理。  代理

這裏用了兩個jar,asm-3.3.1.jar 和cglib-2.2.2.jar 注意版本號哦,否則坑

/**
 *
 * 相信你必定也知道水滸傳的拼命三郎石秀吧,他的結拜兄弟楊雄的老婆,潘雲巧也是個水性楊花的女人
 * 他和師兄(一個和尚偷情)
 */
public class PanYunQiao {
    public void betrayal(){
        System.out.println("正在和和尚偷情...");
    }
}



**
 * cglib動態代理
 *
 * 王婆變身動態代理
 *
 * cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現加強,但由於採用的是繼承,因此不能對final修飾的類進行代理。
 */
public class WangPoCglibProxy implements MethodInterceptor {

    private Object target;
    /**
     * 建立代理對象
     *
     * @param target
     * @return
     */
    public Object getInstance(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        // 回調方法
        enhancer.setCallback(this);
        // 建立代理對象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.err.println("+++++++++cglib開始切入++++++++++++");

        methodProxy.invokeSuper(obj, args);

        System.err.println("+++++++++++cglib結束切入++++++++++");

        return null;
    }
}



/**
         * cglib動態代理
         */
        WangPoCglibProxy wangPoCglibProxy = new WangPoCglibProxy();

        PanYunQiao panYunQiao = new PanYunQiao();

        PanYunQiao pan = (PanYunQiao) wangPoCglibProxy.getInstance(panYunQiao);

        pan.betrayal();



相關文章
相關標籤/搜索