Design pattern--代理模式
2017-06-03 16:25
162 查看
Design pattern–代理模式
代理模式是常用的设计模式之一,在retrofit2源码分析过程中,看到了动态代理的使用,非常精妙,有必要深入理解下。代理模式有两种,静态代理和动态代理。静态代理
代理(Proxy)是一种设计模式,即通过代理对象访问目标对象,好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.看一个例子
// Subject.java public interface Subject { void operation(); } // RealSubject.java public class RealSubject implements Subject{ @Override public void operation() { System.out.println("operation by RealSubject"); } } // ProxySub.java public class ProxySub implements Subject{ Subject subject; public ProxySub(Subject subject) { this.subject = subject; } @Override public void operation() { System.out.println("do other things"); subject.operation(); } } // MainActivity.java public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ProxySub sub = new ProxySub(new RealSubject()); sub.operation(); } }
ProxySub是一个代理类,目标对象是RealSubject,最终调用的是RealSubject#operation方法,但是调用RealSubject#operation前后可以做些额外的操作。
静态代理总结:
1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.
2.缺点:
因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类. 同时,一旦接口增加方法,目标对象与代理对象都要维护.
如何解决静态代理中的缺点呢?答案是使用动态代理
动态代理
通过InvocationHandler来完成动态代理// ProxySubject.java public class ProxySubject implements InvocationHandler{ Subject subject; public ProxySubject(Subject subject) { this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("method->" + method.getName()); return method.invoke(subject, args); } } // MainActivity.java final Subject subject = new RealSubject(); ProxySubject proxy = new ProxySubject(subject); Subject sub = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), proxy); sub.operation();
运行一下:
06-03 16:05:31.683 2173-2173/com.rico.proxy I/System.out: method->operation 06-03 16:05:31.683 2173-2173/com.rico.proxy I/System.out: operation by RealSubject
调用过程大致是:newProxyInstance得到一个动态生成的代理类 $Proxy0,这个类继承了Proxy并且实现了Subject接口,所以调用$Proxy0#operation方法,实际上调用的是super.h.invoke(this, , ),也就是父类Proxy的h的invoke方法,也就是ProxySubject的invoke方法,然后通过反射method.invoke(subject, args);调用RealSubject#operation接口,有点绕,但是基本上说清楚了
查看源码发现$Proxy0正式调用getProxyClass0构建出来的,通过反射得到所有的构造方法,然后调用newInstance(cons, h);动态构建$Proxy0,传入的h正式我们ProxySubject实例
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 = getProxyClass0(loader, interfaces); /* * Invoke its constructor with the designated invocation handler. */ try { final Constructor<?> cons = cl.getConstructor(constructorParams); return newInstance(cons, h); } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } }
下面看下$Proxy0的源码
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy0 extends Proxy implements Manager { private static Method m1; private static Method m0; private static Method m3; private static Method m2; static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m3 = Class.forName("com.ml.test.Manager").getMethod("modify", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); } catch (NoSuchMethodException nosuchmethodexception) { throw new NoSuchMethodError(nosuchmethodexception.getMessage()); } catch (ClassNotFoundException classnotfoundexception) { throw new NoClassDefFoundError(classnotfoundexception.getMessage()); } } public $Proxy0(InvocationHandler invocationhandler) { super(invocationhandler); } @Override public final boolean equals(Object obj) { try { return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue(); } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } @Override public final int hashCode() { try { return ((Integer) super.h.invoke(this, m0, null)).intValue(); } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final void operation() { try { super.h.invoke(this, m3, null); return; } catch (Error e) { } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } @Override public final String toString() { try { return (String) super.h.invoke(this, m2, null); } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } }
代理模式就分析这么多了,以上!
相关文章推荐
- Design Pattern—— static proxy pattern 静态代理模式
- Design Pattern—— Dynamic Proxy Pattern 动态代理模式
- Design Pattern_Proxy(代理模式)
- 设计模式笔记 – Proxy 代理模式 (Design Pattern)
- Design Pattern—— Dynamic Proxy Pattern(三) 动态代理模式
- Design Pattern:代理模式
- Design Pattern—— Dynamic Proxy Pattern(二) 动态代理模式
- [Design Pattern]Python设计模式——代理模式
- 设计模式之代理模式 (三)
- 静态代理模式
- 三种代理模式
- 设计模式——代理模式及在jdk中的应用
- 代理模式
- 代理模式
- 大话设计模式——代理模式
- 设计模式--代理模式
- 黑马程序员_代理设计模式
- 设计模式(五)—— 代理模式
- python设计模式(四)--代理模式(中)
- 使用自动生成java文件和自动编译的静态代理模式