java-动态代理-从源码分析
来源:互联网 发布:fft c语言代码 编辑:程序博客网 时间:2024/06/05 05:24
现在有一个接口UserService
public interface UserService { /** * 目标方法 */ public abstract void add(); }
有一个实现类
public class UserServiceImpl implements UserService { /* (non-Javadoc) * @see dynamic.proxy.UserService#add() */ public void add() { System.out.println("--------------------add---------------"); } }
有一个InvocationHandler类
public class MyInvocationHandler implements InvocationHandler { // 目标对象 private Object target; /** * 构造方法 * @param target 目标对象 */ public MyInvocationHandler(Object target) { super(); this.target = target; } /** * 执行目标对象的方法 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在目标对象的方法执行之前简单的打印一下 System.out.println("------------------before------------------"); // 执行目标对象的方法 Object result = method.invoke(target, args); // 在目标对象的方法执行之后简单的打印一下 System.out.println("-------------------after------------------"); return result; } }
现在就可以实现动态代理啦
public class ProxyTest { @Test public void testProxy() throws Throwable { // 实例化目标对象 UserService userService = new UserServiceImpl(); // 实例化InvocationHandler MyInvocationHandler invocationHandler = new MyInvocationHandler(userService); // 根据目标对象生成代理对象,参数为:一个classloader,一个接口数组,一个invocationHandler UserService proxy = (UserService)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),userService.getClass().getInterfaces(), invocationHandler ); // 调用代理对象的方法 proxy.add(); } }
解析
当你刚看到动态代理时,会感到非常疑惑与混乱。但最终的结果告诉我们,最后执行的代码是invocationHandler.invoke方法:
System.out.println("------------------before------------------"); // 执行目标对象的方法 Object result = method.invoke(target, args); // 在目标对象的方法执行之后简单的打印一下 System.out.println("-------------------after------------------");
通过查看Proxy.newProxyInstance方法的源码,我发现,有用的就两句话,大概意思是:
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
Class proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
Constructor cons = proxyClass.getConstructor(InvocationHandler.class);
return (Object) cons.newInstance(new Object[] { invocationHandler });
java用Proxy.newInstance的第二个参数:接口数组,构造了一个新的class,并且返回了一个用该class构造的一个新的对象,通过反编译工具,来将该class文件反编译为一个java文件,来看看究竟:
public final class $Proxy11 extends Proxy implements UserService { public $Proxy11(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 void add() { try { super.h.invoke(this, m3, null); return; } 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 String toString() { try { return (String)super.h.invoke(this, m2, null); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } private static Method m1; private static Method m3; private static Method m0; private static Method m2; static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m3 = Class.forName("dynamic.proxy.UserService").getMethod("add", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", 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()); } } }
也就是说当我们调用proxy.add()方法时,add方法的代码为:
super.h.invoke(this, m3, null);
super.h:
h也就是我们我们构造这个类时传入的参数,上面提到过,具体代码如下:
return (Object) cons.newInstance(new Object[] { invocationHandler });
一个我们定义过的类的实例。
m3:
m3 = Class.forName(“dynamic.proxy.UserService”).getMethod(“add”, new Class[0]);
现在一切就很清晰明了了吧,知其然知其所以然,现在就可以灵活运用java动态代理了。
参考文章:http://rejoy.iteye.com/blog/1627405
- 【Java】从源码分析动态代理机制
- java-动态代理-从源码分析
- Java 动态代理源码分析
- Java 动态代理源码分析
- Java基础:JDK动态代理源码分析
- JDK动态代理源码分析
- cglib动态代理源码分析
- Java动态代理分析
- Java动态代理分析
- java-动态代理分析
- JAVA 动态代理(proxy)的实现和源码分析
- Java动态代理的源码分析;Proxy与InvocationHandler
- JAVA 动态代理(proxy)的实现和源码分析
- jdk 源码分析(21)java 动态代理和反射
- 【动态代理】从源码实现角度剖析JDK动态代理
- 从代理模式到Java动态代理
- java代理(三、动态代理源码)
- Java设计模式-代理模式之动态代理(附源码分析)
- mac系统中如何利用命令框里进行数据库迁移
- javaScript 外部对象2
- 使用Fresco实现大图浏览(支持手势放大、拖拽)
- 使用Sblime Text开发TypeScript(TS)的编译环境搭建
- FIDO Metadata Statements(译)
- java-动态代理-从源码分析
- 蓝桥杯 操作格子(线段树例题)
- ASP.NET C#学习二(数据库开发)
- h5本地存储的sessionStorage和localStorage
- Keras Tensorflow TF_NewStatus错误修改
- Java基础——常量
- 1583
- UML类图画法及其之间的几种关系
- test