Java动态代理学习
2015-11-19 16:24
281 查看
刚在Java虚拟机书上看到了说Java的动态代理的实现机制,使我困惑很久的问题终于被解开,所以在这里记录一下.
先奉上测试代码(每个类或接口一个.java文件):
运行结果是:
这句是代理打印的!
hello
添加System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”);这一条语句的作用是为了保存动态生成的代理类的字节码文件.
这里的黑匣子只有一句:
Proxy.newProxyInstance(originObj.getClass().getClassLoader(), originObj.getClass().getInterfaces(), this);
这条方法调用会在运行时生成一个代理类,代理SayHello接口的所有方法.
要看使如何做到得,必须查看自动生成的代理类的源码,这里用反编译工具jd-gui将生成的字节码文件反编译,得到的代码是:
书上说的是生成字节码文件是通过class文件规范去拼装,这个就先不理他了.
先奉上测试代码(每个类或接口一个.java文件):
[code]//等会儿会被代理的接口 //Java自带的动态代理生成的是代理接口的对象 public interface SayHello { void sayHello(); } //上面接口的一个实现类 public class HelloImpl implements SayHello { public void sayHello() { System.out.println("hello"); } } //会自动生成代理对象的动态代理类 public class DynamicProxy implements InvocationHandler { //代理的是这个类的接口 Object originObj; public DynamicProxy(Object originObj) { this.originObj = originObj; } public Object getProxy() { return Proxy.newProxyInstance(originObj.getClass().getClassLoader(), originObj.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("这句是代理打印的!"); return method.invoke(originObj, args); } } //main方法 public class DynamicProxyTest { public static void main(String[] args) { System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); //先生成一个原始实现了SayHello接口的实例,因为需要这个实例去生成代理实例 HelloImpl originHello = new HelloImpl(); //得到可以动态生成代理实例的对象 DynamicProxy proxy = new DynamicProxy(originHello); //得到代理SayHello接口的实例对象 SayHello proxyHello = (SayHello) proxy.getProxy(); proxyHello.sayHello(); } }
运行结果是:
这句是代理打印的!
hello
添加System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”);这一条语句的作用是为了保存动态生成的代理类的字节码文件.
这里的黑匣子只有一句:
Proxy.newProxyInstance(originObj.getClass().getClassLoader(), originObj.getClass().getInterfaces(), this);
这条方法调用会在运行时生成一个代理类,代理SayHello接口的所有方法.
要看使如何做到得,必须查看自动生成的代理类的源码,这里用反编译工具jd-gui将生成的字节码文件反编译,得到的代码是:
[code]package com.sun.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; import top.geekgao.proxy.SayHello; public final class $Proxy0 extends Proxy implements SayHello { private static Method m1; private static Method m3; private static Method m2; private static Method m0; public $Proxy0(InvocationHandler paramInvocationHandler) { super(paramInvocationHandler); } public final boolean equals(Object paramObject) { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } //主要看这里,这里是代理类的核心 public final void sayHello() { try { //this.h代表的就是Proxy.newProxyInstance()的最后一个参数,即上面main方法中的proxy对象 //有了h就可以调用它的invoke()方法 //m3代表的就是sayHello()方法,并且没有参数,所以是null //这样就可以调用每一个方法了 this.h.invoke(this, m3, null); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final String toString() { try { return (String)this.h.invoke(this, m2, null); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final int hashCode() { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m3 = Class.forName("top.geekgao.proxy.SayHello").getMethod("sayHello", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); return; } catch (NoSuchMethodException localNoSuchMethodException) { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch (ClassNotFoundException localClassNotFoundException) { throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); } } }
书上说的是生成字节码文件是通过class文件规范去拼装,这个就先不理他了.
相关文章推荐
- java读取csv数据到list缓存,并对list集合分组统计结果
- Eclipse用法和技巧十七:覆盖父类方法
- eclipse开发用ant生成myeclipse那样的执行文件夹
- Struts2 Ajax---Action传值到JSP页面 Json格式
- eclipse下git不能拉取错误解决小记
- Eclipse用法和技巧十六:自动添加未实现方法2
- Java Memory Architecture (Model), Garbage Collection and Memory Leaks
- Java打印菱形
- Spring事务配置的五种方式
- java中的HashSet集合
- Java并发编程:volatile关键字解析
- java缩放图片、java裁剪图片代码工具类
- SSH:Struts1框架(ActionForm注册类型自动转换)
- 浅谈Java中的hashcode方法
- Java 对 Properties 文件的操作
- 关于Java概述(参考官方文档)
- Spring 注解 @Resource和@Autowired
- Java中使用Runtime和Process类运行外部程序
- Eclipse用法和技巧十五:自动添加未实现方法1
- javaSE API的下载与javaEE API的在线查看