问题:Java动态代理
来源:互联网 发布:域名可以干嘛 编辑:程序博客网 时间:2024/06/11 04:25
之前学习java时,对动态代理,只知其然,不知其所以然。一直想着深入理解动态代理,今天研究了一下,虽然没有完全研究明白,先在这里做个总结,如果读者知道其中的答案,望留言告知。
- 首先要实现InvocationHandler接口,这个接口只有一个方法invoke(Object proxy, Method method, Object[] args) throws Throwable
- Animal animal = (Animal) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),ds );其中 Animal 是被代理的类实现的接口,cls是实现Animal接口的类的Class,ds 实现InvocationHandler接口的类的对象。
- 利用animal调用被代理的方法。
package main.proxy;public interface Animal { abstract public void eat(); }
package main.proxy;public class Frog implements Animal { public static int i=0; public Frog() { System.out.println("in Frog"+i++); } public void eat() { System.out.println( " 青蛙吃虫子 " ); } }
package main.proxy;import java.lang.reflect.Method;import java.lang.reflect.InvocationHandler;public class DynamicProxy implements InvocationHandler { private Object obj; public DynamicProxy() {} public DynamicProxy(Object obj) { this.obj = obj; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println( " before calling " + method); Object pObj=method.invoke(obj,args); //System.out.println(sub==prox); System.out.println( " after calling " + method); return null ; }}
package main.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;import java.io.FileOutputStream;import java.io.IOException;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Client { static public void main(String[] args) throws Throwable { Frog rs = new Frog(); // 在这里指定被代理类 InvocationHandler dp= new DynamicProxy(rs); Class cls = rs.getClass(); Animal animal = (Animal) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),dp ); Constructor[] cons= animal.getClass().getConstructors(); Method[] mds= animal.getClass().getMethods(); Field[] fls=animal.getClass().getFields(); Class[] ifs=animal.getClass().getInterfaces(); System.out.println("开始"); System.out.println("构造器"); for(Constructor c:cons) System.out.println(c); System.out.println("方法"); for(Method m:mds) System.out.println(m); System.out.println("成员变量"); for(Field f:fls) System.out.println(f); System.out.println("接口"); for(Class c:ifs) System.out.println(c); System.out.println("end"); // subject.request(); }}
代码的运行结果
in Frog0class com.sun.proxy.$Proxy0开始构造器public com.sun.proxy.$Proxy0(java.lang.reflect.InvocationHandler)方法public final boolean com.sun.proxy.$Proxy0.equals(java.lang.Object)public final java.lang.String com.sun.proxy.$Proxy0.toString()public final int com.sun.proxy.$Proxy0.hashCode()public final void com.sun.proxy.$Proxy0.eat()public static boolean java.lang.reflect.Proxy.isProxyClass(java.lang.Class)public static java.lang.reflect.InvocationHandler java.lang.reflect.Proxy.getInvocationHandler(java.lang.Object) throws java.lang.IllegalArgumentExceptionpublic static java.lang.Class java.lang.reflect.Proxy.getProxyClass(java.lang.ClassLoader,java.lang.Class[]) throws java.lang.IllegalArgumentExceptionpublic static java.lang.Object java.lang.reflect.Proxy.newProxyInstance(java.lang.ClassLoader,java.lang.Class[],java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentExceptionpublic final void java.lang.Object.wait() throws java.lang.InterruptedExceptionpublic final void java.lang.Object.wait(long,int) throws java.lang.InterruptedExceptionpublic final native void java.lang.Object.wait(long) throws java.lang.InterruptedExceptionpublic final native java.lang.Class java.lang.Object.getClass()public final native void java.lang.Object.notify()public final native void java.lang.Object.notifyAll()成员变量接口interface main.proxy.Animalend
从打印结果可以看出,这个代理类实现了Animal这个接口,仅有一个构造函数且参数是java.lang.reflect.InvocationHandler。
疑惑:
- invoke这个函数是怎么被调用的。他的第一个参数作用是什么?
在网上找了些资料,http://rejoy.iteye.com/blog/1627405 大神将字节码输出到文件,然后反编译,由于版本的问题,他的方法我无法使用,他的结果和我通过反射机制获取的结果有所出入;现在的问题是 怎么动态获取类的字节码?
下面是我查看的java源码 版本是java-8u74
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { Objects.requireNonNull(h);//判断是否为空,为空抛出空对象异常 final Class<?>[] intfs = interfaces.clone();//克隆 final SecurityManager sm = System.getSecurityManager();/*SecurityManager在Java中被用来检 查应用程序是否能访问一些有限的资源,例如文件、套接字(socket)等等。它可以用在那些 具有高安全性要求的应用程序中。通过打开这个功能, 我们的系统资源可以只允许进行安全的操作。*/ if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs);// Check permissions required to create a Proxy class. } /* * Look up or generate the designated proxy class. */ Class<?> cl = getProxyClass0(loader, intfs);//Generate a proxy class. /* * Invoke its constructor with the designated invocation handler. */ try { if (sm != null) { // do permission check if the caller is in a different runtime package // of the proxy class checkNewProxyPermission(Reflection.getCallerClass(), cl);// } // constructorParams= { InvocationHandler.class } parameter types of a proxy class constructor */ //getConstructor 会先检测是否有权限,若访问具被拒绝则抛出securityexception //获得参数为 InvocationHandler的构造器 final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } //对象数组 包含 h 使用InvocationHandler为参数返回一个实例 return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } }
1 0
- 问题:Java动态代理
- Java 代理,动态代理
- Java动态代理(解决编码问题)
- Java动态代理的异常处理问题
- [Java] Java 动态代理
- java代理及动态代理
- java代理模式--动态代理
- Java静态代理、动态代理
- Java 代理之 动态代理
- Java 代理与动态代理
- java静态代理,动态代理
- 代理模式&java动态代理
- Java代理与动态代理
- Java静态代理动态代理
- JAVA代理模式--动态代理
- java 代理和动态代理
- JAVA动态代理 代理模式
- Java动态代理--jdk代理
- treap by:刘汝佳
- iOS 硬件 大头针 - 终极 - 自定义样式
- linux点滴
- zzulioj 1874 蛤玮学计网 (“玲珑杯”郑州轻工业学院第八届ACM程序设计大赛暨河南高校邀请赛-正式赛)
- 递归求解 猴子吃桃
- 问题:Java动态代理
- java问题探讨之clone浅拷贝与深拷贝
- iOS 硬件 导航 - APP去做
- 产品经理的段位——说说腾讯的产品职级
- iOS 硬件 导航 - 系统请求数据 绘制路线
- View的layout
- C++ STL 方法求全排列
- LeetCode------Contains Duplicate
- sublime text3里搭建python