动态代理详解
来源:互联网 发布:科罗拉多州立大学知乎 编辑:程序博客网 时间:2024/05/21 20:26
动态代理使用:
public interface Subject { public void doSomething(); } public class RealSubject implements Subject { public void doSomething() { System.out.println( "call doSomething()" ); } } public class ProxyHandler implements InvocationHandler { private Object proxied; public ProxyHandler( Object proxied ) { this.proxied = proxied; } public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable { //在转调具体目标对象之前,可以执行一些功能处理 //转调具体目标对象的方法 return method.invoke( proxied, args); //在转调具体目标对象之后,可以执行一些功能处理 } }
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import sun.misc.ProxyGenerator; import java.io.*; public class DynamicProxy { public static void main( String args[] ) { RealSubject real = new RealSubject(); Subject proxySubject = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(), new Class[]{Subject.class}, new ProxyHandler(real)); proxySubject.doSomething(); //write proxySubject class binary data to file createProxyClassFile(); } public static void createProxyClassFile() { String name = "ProxySubject"; byte[] data = ProxyGenerator.generateProxyClass( name, new Class[] { Subject.class } ); try { FileOutputStream out = new FileOutputStream( name + ".class" ); out.write( data ); out.close(); } catch( Exception e ) { e.printStackTrace(); } } }
动态代理内部实现:
首先来看看Proxy类的内部代码的主要静态变量的实现:
// 映射表:用于维护类装载器对象到其对应的代理类缓存private static Map loaderToCache = new WeakHashMap(); // 标记:用于标记一个动态代理类正在被创建中private static Object pendingGenerationMarker = new Object(); // 同步表:记录已经被创建的动态代理类类型,主要被方法 isProxyClass 进行相关的判断private static Map proxyClasses = Collections.synchronizedMap(new WeakHashMap()); // 关联的调用处理器引用protected InvocationHandler h;Proxy的构造方法:
// 由于 Proxy 内部从不直接调用构造函数,所以 private 类型意味着禁止任何调用private Proxy() {} // 由于 Proxy 内部从不直接调用构造函数,所以 protected 意味着只有子类可以调用protected Proxy(InvocationHandler h) {this.h = h;}Proxy的静态方法newProxyInstance:
public static Object newProxyInstance(ClassLoader loader, Class<?>[]interfaces,InvocationHandler h) throws IllegalArgumentException { // 检查 h 不为空,否则抛异常 if (h == null) { throw new NullPointerException(); } // 获得与指定类装载器和一组接口相关的代理类类型对象 Class cl = getProxyClass(loader, interfaces); // 通过反射获取构造函数对象并生成代理类实例 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()); } }类Proxy的getProxyClass方法调用ProxyGenerator的 generateProxyClass方法产生ProxySubject.class的二进制数据:
public static byte[] generateProxyClass(final String name, Class[] interfaces)我们可以import sun.misc.ProxyGenerator,调用 generateProxyClass方法产生binary data,然后写入文件,最后通过反编译工具来查看内部实现原理。 反编译后的ProxySubject.java, (Proxy的静态方法newProxyInstance产生的class文件反编译后的java文件)
import java.lang.reflect.*; public final class ProxySubject extends Proxy implements Subject { private static Method m1; private static Method m0; private static Method m3; private static Method m2; public ProxySubject(InvocationHandler invocationhandler) { super(invocationhandler); } public final boolean equals(Object obj) { try { return ((Boolean)super.h.invoke(this, m1, new Object[] { obj })).booleanValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int hashCode() { try { return ((Integer)super.h.invoke(this, m0, null)).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final void doSomething() { try { super.h.invoke(this, m3, null); return; } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final String toString() { try { return (String)super.h.invoke(this, m2, null); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } 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("Subject").getMethod("doSomething", 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()); } } }
0 0
- Java动态代理详解
- java动态代理详解
- Java动态代理详解
- java动态代理详解
- 详解java动态代理
- java 动态代理详解
- Java动态代理详解
- JDK动态代理详解
- java动态代理详解
- Cglib动态代理详解
- JAVA动态代理详解
- Java动态代理详解
- Java动态代理详解
- java动态代理详解
- Java动态代理详解
- java动态代理详解
- Java动态代理详解
- Java动态代理详解
- javaScript prototype原型的理解
- 【转载】css sprite css雪碧图生成工具
- static_cast,dynamic_cast,const_cast和reinterpret_cast
- CUDA的Threading:Block和Grid设定
- Qt layout布局
- 动态代理详解
- iOS及Mac开源项目和学习资料【超级全面】
- Kinect骨骼数据与彩色影像和深度影像的对齐
- 基于rails的schedule网站开发(12):index View页面的重构
- Java笔记5:单例模式
- 网站测试都要测试哪些及、如何进行测试
- 大师之路解惑基础概念篇:Tomcat与servlet联系与区别
- css reset归纳
- iOS开发 - 登陆post请求遇到的问题