一 代理模式java
定义:在访问目标对象的时候,提供一种间接访问的方法,经过代理对象去访问目标对象,达到客户端的目的。api
好处:保护目标对象;在目标对象的行为基础上,代理对象能够增长本身的处理,使得同一个目标对象能够知足不一样的客户端的目的。app
代理模式的模型:ide
涉及三个角色:函数
RealSubject:目标对象,也是真正要作事情的人。ui
Proxy:代理对象,持有对目标对象的引用,暴露给客户端,经过操做目标对象来完成客户端的目的。而且,代理对象能够在操做目标对象的先后作一些自定义的行为,灵活扩展了目标对象。this
Subject:目标对象和代理对象的抽象,以便在任何使用目标对象的地方均可以使用代理对象。Subject能够是一个接口也能够是一个抽象类。spa
二 静态代理代理
以最简单的形式实现上述模型code
public interface Subject { void doRequst(); } public class RealSubject implements Subject { @Override public void doRequst() { System.out.println("it's the thing i really want to do"); } } public class Proxy implements Subject { private Subject subject; public Proxy(Subject subject){ this.subject = subject; } @Override public void doRequst() { System.out.println("before do the real thing"); subject.doRequst(); System.out.println("after do the real thing"); } } public class Client { public static void main(String[] args) { Proxy proxy = new Proxy(new RealSubject()); proxy.doRequst(); } } /** before do the real thing it's the thing i really want to do after do the real thing **/
这种实现方式即常说的静态代理,有几个方面的约束:
1 代理对象和目标对象须要实现共同的接口,接口有变更,目标对象和代理对象都须要维护。
2 想要代理其余的目标对象,须要新增代理类。
三 动态代理
先看java实现动态代理的几个主要角色
1 Proxy :java.lang.reflect.Proxy,jdk api提供的代理类的主类,该类提供方法动态生成代理类,生成的时候须要指定一组接口(即代理类和目标对象要实现哪些接口)
public static Object newProxyInstance(ClassLoader var0, Class<?>[] var1, final InvocationHandler var2) throws IllegalArgumentException /** 提供了这个静态方法用于动态生成代理类 var0: 目标对象的类加载器 var1: 代理类要实现哪些接口,即目标对象实现的接口 var2: 处理器,代理类具体要作什么写在处理器中 **/
2 InvocationHandler :java.lang.reflect.InvocationHandler
/** @param proxy the proxy instance that the method was invoked on 代理对象,执行invoke的时候实际上是在替这个proxy执行 @param method the {@code Method} instance corresponding to the interface method invoked on the proxy instance. The declaring class of the {@code Method} object will be the interface that the method was declared in, which may be a superinterface of the proxy interface that the proxy class inherits the method through. 目标对象要执行的方法 @param args an array of objects containing the values of the arguments passed in the method invocation on the proxy instance, or {@code null} if interface method takes no arguments. Arguments of primitive types are wrapped in instances of the appropriate primitive wrapper class, such as {@code java.lang.Integer} or {@code java.lang.Boolean}. 执行方法须要的参数 **/ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
java动态代理实例
public interface Subject { void doRequest(); } public class RealSubject1 implements Subject { @Override public void doRequest() { System.out.println("RealSubject1 want to sing"); } } public class RealSubject2 implements Subject { @Override public void doRequest() { System.out.println("RealSubject2 want to dance"); } } public class RealInvocationHandler implements InvocationHandler { private Object subject; public RealInvocationHandler(Object subject){ this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before process"); Object result = method.invoke(subject,args); System.out.println("after process"); return result; } } public class Client { public static void main(String[] args) { Subject realSubject1 = new RealSubject1(); InvocationHandler handler1 = new RealInvocationHandler(realSubject1); Subject subject1 = (Subject) Proxy.newProxyInstance(realSubject1.getClass().getClassLoader(),realSubject1.getClass().getInterfaces(),handler1); subject1.doRequest(); System.out.println("-----------------------"); Subject realSubject2 = new RealSubject2(); InvocationHandler handler2 = new RealInvocationHandler(realSubject2); Subject subject2 = (Subject)Proxy.newProxyInstance(realSubject2.getClass().getClassLoader(),realSubject2.getClass().getInterfaces(),handler2); subject2.doRequest(); } } /** before process RealSubject1 want to sing after process ----------------------- before process RealSubject2 want to dance after process **/
与静态代理作个比较:
不须要挨个写代理类,想代理其余的,动态new一个代理类
相关源码解析
Proxy.newProxyInstance生成的代理具有什么以及为何能够转换成目标对象
protected InvocationHandler h; public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { // 校验handler if (h == null) { throw new NullPointerException(); } final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /* * Proxy维护了一个proxyClassCache,若是想要的代理类已经有实现了指定接口的loader定义好了,直接返回cache的备份 * 不然,经过ProxyClassFactory 生成一个代理类,实现指定的intfs */ Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. */ try { //获取构造函数,将传进来的h赋给proxy内部持有的Invokerhanler对象 final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { // create proxy instance with doPrivilege as the proxy class may // implement non-public interfaces that requires a special permission return AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { return newInstance(cons, ih); } }); } else { return newInstance(cons, ih); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } }
因此,Proxy生成的代理对象具有一个invokehandler对象的引用;而且实现了目标对象实现的接口,由于能够转换为目标对象的抽象
InvokeHandler为何能够完成目标对象方法的执行
如上述例子中目标对象RealSubject1要执行doRequest方法,Proxy生成的代理类也会实现这个方法,大概以下:
public final void doRequest() { //这个会调用invokehandler的invoke方法,这里的h便是父类Proxy的h,经过newProxyInstance传进来的 try { this.h.invoke(this, m3, null); return; } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } }
有了InvocationHandler 可使Proxy从具体的代码逻辑抽离出来,更方便统一的生成代理类。
后续todo:
Proxy生成的代理对象的具体剖析
method.invoke具体作了什么