如何理解代理?

一、本节主要点

  1. 代理的概念
  2. 静态代理和动态代理

代理的概念

什么是代理呢?

代理,就是一个角色代表另一个角色去完成某件事。

比如,你肚子饿了,又懒得出去吃饭,这时候,你的朋友正好要出去,你让他帮忙打包。那他就是代理类。你就是委托他去做事。

这个代理类在帮你打包的同时,他还可以自己打包,或者顺便去买包烟。

那这个代理类有什么作用呢?

就是完成目标类 之前可以做点其他什么的。之后可以做点什么。

静态代理

在运行之前,代理的类已经确定。

例子如下:

1、Pack 接口

public interface Pack {
    public void giveMePack();
}

2、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("垃圾太多了,倒掉吧");
    }
}

4、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 类。

1、InvocationHandler 接口

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

Object proxy:被代理的对象。 
     Method method:要调用的方法 
     Object[] args:方法调用需要的参数

2、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动态代理可以看出。代理类的变化:

1、实现了InvocationHandler接口。

2、把目标对象和动态代理绑定起来。便于客户端调用。

3、实现invoke 方法。

JDK动态代理,只能代理实现接口的类。如果针对类来实现代理,则需要cglib 代理了。


代理模式的本质:控制对象访问

原文地址:https://www.cnblogs.com/pan2011/p/3857404.html