如何理解代理?

1、本節主要點java

  1. 代理的概念
  2. 靜態代理和動態代理

 

代理的概念 ide

什麼是代理呢?this

代理,就是一個角色表明另外一個角色去完成某件事。spa

好比,你肚子餓了,又懶得出去吃飯,這時候,你的朋友正好要出去,你讓他幫忙打包。那他就是代理類。你就是委託他去作事。代理

這個代理類在幫你打包的同時,他還能夠本身打包,或者順便去買包煙。code

那這個代理類有什麼做用呢? 對象

就是完成目標類 以前能夠作點其餘什麼的。以後能夠作點什麼。blog

靜態代理接口

在運行以前,代理的類已經肯定。get

例子以下:

一、Pack 接口

public interface Pack {
    public void giveMePack();
}

二、PackImpl 類

public class PackImpl implements Pack {
    @Override
    public void giveMePack() {
        System.out.println("幫我打包吧,中午下雨啊");
    }
}

3 proxy 代理類

/**代理類
 * Created by hp on 14-7-27.
 */
public class Proxy implements Pack {

    public PackImpl pack;

    public Proxy(PackImpl pack) {
        this.pack = pack;
    }

    @Override
    public void giveMePack() {
        System.out.println("哥去買包煙先,再幫你打包");
        pack.giveMePack();
        System.out.println("垃圾太多了,倒掉吧");
    }
}

四、ClientText 類

public class ClientText {
    public static void main(String[] args) {
        PackImpl pack = new PackImpl();
        Proxy proxy = new Proxy(pack);
        proxy.giveMePack();

    }
}

以上就是靜態代理的實現代碼。它有一個特色:

一個代理類只服務於一個接口。

這樣若是有許多這樣的代理,那就有不少的代理類出現。因此,最好是有一個代理類能夠完成所有的代理功能。這就是下面要講的動態代理了。

動態代理

解釋一下,動態代理就是在程序運行中由Java的反射機制動態生成。

先看一下JDK對動態代理的支持,java.lang.reflect 包中的 InvocationHandler 接口和 Proxy 類。

一、InvocationHandler 接口

public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable;

Object proxy:被代理的對象。 
     Method method:要調用的方法 
     Object[] args:方法調用須要的參數

二、Proxy類

這個是完成代理的操做類。其中有一個方法是這樣的

ClassLoader loader:類加載器 
     Class<?>[] interfaces:獲得所有的接口 
     InvocationHandler h:獲得InvocationHandler接口的子類實例

public static Object newProxyInstance(ClassLoader loader,
                      Class<?>[] interfaces,
                      InvocationHandler h)
    throws IllegalArgumentException
    {
    if (h == null) {
        throw new NullPointerException();
    }

    /*
     * Look up or generate the designated proxy class.
     */
    Class cl = getProxyClass(loader, interfaces);

    /*
     * Invoke its constructor with the designated invocation handler.
     */
    try {
        Constructor cons = cl.getConstructor(constructorParams);
        return (Object) cons.newInstance(new Object[] { h });
    } catch (NoSuchMethodException e) {
        throw new InternalError(e.toString());
    } catch (IllegalAccessException e) {
        throw new InternalError(e.toString());
    } catch (InstantiationException e) {
        throw new InternalError(e.toString());
    } catch (InvocationTargetException e) {
        throw new InternalError(e.toString());
    }
    }

 

代理類實例:

/**
 * JDK 的動態代理
 * Created by hp on 14-7-27.
 */
public class DynamicProxy implements InvocationHandler {

    private Object object;

    public Object getProxyInterface(Object object) {
        this.object = object;
        // 獲取代理對象
        Object o = Proxy.newProxyInstance(object.getClass().getClassLoader(),
                object.getClass().getInterfaces(), this);
        return o;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("哥去買包煙先,再幫你打包");
        Object result = method.invoke(object, args);
        System.out.println("垃圾太多了,倒掉吧");
        return result;
    }
}

從JDK動態代理能夠看出。代理類的變化:

一、實現了InvocationHandler接口。

二、把目標對象和動態代理綁定起來。便於客戶端調用。

三、實現invoke 方法。

JDK動態代理,只能代理實現接口的類。若是針對類來實現代理,則須要cglib 代理了。


代理模式的本質:控制對象訪問