一、本节主要点
- 代理的概念
- 静态代理和动态代理
代理的概念
什么是代理呢?
代理,就是一个角色代表另一个角色去完成某件事。
比如,你肚子饿了,又懒得出去吃饭,这时候,你的朋友正好要出去,你让他帮忙打包。那他就是代理类。你就是委托他去做事。
这个代理类在帮你打包的同时,他还可以自己打包,或者顺便去买包烟。
那这个代理类有什么作用呢?
就是完成目标类 之前可以做点其他什么的。之后可以做点什么。
静态代理
在运行之前,代理的类已经确定。
例子如下:
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 代理了。
代理模式的本质:控制对象访问