動態代理的兩種實現方式(JDK/Cglib) 動態代理的兩種實現方式(JDK/Cglib) 設計模式—代理模式

===========================================html

    原文連接: 動態代理的兩種實現方式(JDK/Cglib) 轉載請註明出處!java

===========================================設計模式

什麼是代理模式?(設計模式—代理模式)
  代理模式:在調用處不直接調用目標類進行操做,而是調用代理類,而後經過代理類來調用目標類進行操做。在代理類調用目標類的先後能夠添加一些預處理和後處理操做來完成一些不屬於目標類的功能。
爲何要使用代理模式?
  經過代理模式能夠實現對目標類調用的控制、在目標類調用前/後進行一些不屬於目標類的操做,如:數據驗證、預處理、後處理、異常處理等
什麼是靜態代理什麼是動態代理?
  靜態代理:代理類只能實現對」特定接口的實現類「進行代理
  動態代理:代理類能夠實現對多種類的代理
jdk代理和cglib代理區別在哪裏?
  jdk動態代理:代理全部「實現的有接口」的目標類
     cglib動態代理:代理任意一個目標類,但對final類和方法沒法代理
     不一樣點:jdk動態代理的目標類必須實現的有接口,由於在調用Proxy.newProxyInstance()的時候須要傳入目標類的接口類。而cglib不作此限制。    
   ide

   下面看代碼分析:post

定義一個Person接口測試

package com.zpj.designMode.proxy;

//定義一個Person接口
public interface Person {
    public void doWork();
}

 

添加一個實現類:MrLithis

package com.zpj.designMode.proxy;

//添加一個實現類
public class MrLi implements Person {

    @Override
    public void doWork() {
        System.out.println("-----doWork");
    }

}

 

靜態代理:url

 添加一個靜態代理類Proxyspa

package com.zpj.designMode.proxy;

//靜態代理,代理必須和目標類實現共同的接口
public class Proxy implements Person {
    private Person person;// 被代理人

    //這裏的目標類型決定了該代理類只能代理實現了Person接口的實例,而不能接收其餘類型參數,這也就是靜態代理的侷限性
    public Proxy(Person person) {
        this.person = person;
    }

    @Override
    public void doWork() {
        System.out.println("doSomething-----start");
        person.doWork();
        System.out.println("doSomething-----end");
    }

}

 

靜態代理測試程序:debug

package com.zpj.designMode.proxy;

public class Run {
    public static void main(String[] args) {
        MrLi li = new MrLi();
        Proxy proxy = new Proxy(li);
        //調用處直接調用代理進行目標方法的操做。
        proxy.doWork();
    }
}

 

JDK動態代理:

添加一個代理JDKProxy,該代理實現InvocationHandler接口且覆寫invoke方法。

package com.zpj.designMode.proxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/***
 @author  Perkins Zhu
 @date  2017年3月13日 上午8:41:10
 */
public class JDKProxy implements InvocationHandler {

    private Object person;// 被代理人
     
    
    //這裏的目標類型爲Object,則能夠接受任意一種參數做爲被代理類,實現了動態代理。可是要注意下面的newProxyInstance()中的參數
    public Object getInstance(Object person) {
        this.person = person;
        //與cglib的區別在於這裏構建代理對象的時候須要傳入被代理對象的接口對象,第二個參數。而cglib不須要被代理對象實現任何接口便可        
        return Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this);
    }



    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("doSomething---------start");
        method.invoke(person, args);
        System.out.println("doSomething---------end");
        return null;
    }

}

 

JDK動態代理測試程序

package com.zpj.designMode.proxy.jdk;

import com.zpj.designMode.proxy.MrLi;
import com.zpj.designMode.proxy.Person;

/***
 * @author Perkins Zhu
 * @date 2017年3月13日 上午8:51:31
 */
public class Run {

    public static void main(String[] args) {
        Person person = (Person) new JDKProxy().getInstance(new MrLi());
        //注意這裏的person不是目標類person,而是代理類person:debug的時候顯示null,有'$'標識符
        person.doWork();
    }
}

 

Cglib動態代理:

添加一個CglibProxy代理,同時實現MethodInterceptor接口。

package com.zpj.designMode.proxy.cglib;

import java.lang.reflect.Method;

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

/***
 * @author Perkins Zhu
 * @date 2017年3月13日 上午9:02:54
 */
public class CglibProxy implements MethodInterceptor {
    private Object targetObject;

    // 這裏的目標類型爲Object,則能夠接受任意一種參數做爲被代理類,實現了動態代理
    public Object getInstance(Object target) {
        this.targetObject = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        //注意該處代理的建立過程
        Object proxyObj = enhancer.create();
        return proxyObj;// 返回代理對象
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object obj = null;
        System.out.println("doSomething---------start");
        obj = method.invoke(targetObject, args);
        System.out.println("doSomething---------end");
        return obj;
    }

}

 

Cglib動態代理測試程序

package com.zpj.designMode.proxy.cglib;

import com.zpj.designMode.proxy.MrLi;
import com.zpj.designMode.proxy.Person;

/***
 @author  Perkins Zhu
 @date  2017年3月13日 上午9:07:38
 */
public class Run {

    public static void main(String[] args) {
        Person person = (Person)new CglibProxy().getInstance(new MrLi());
        person.doWork();
    }
}

仔細對比Proxy、CglibProxy和JDKProxy區分靜態代理、JDK動態代理和Cglib動態代理的異同點!

 

-------end

相關文章
相關標籤/搜索