Skip to content

Latest commit

 

History

History
175 lines (157 loc) · 6.67 KB

JDK动态代理的实现原理解析.md

File metadata and controls

175 lines (157 loc) · 6.67 KB

最近在看 Spring AOP 部分的源码,所以对 JDK 动态代理具体是如何实现的这件事产生了很高的兴趣,而且能从源码上了解这个原理的话,也有助于对 spring-aop 模块的理解。话不多说,上代码。

/** * 一般会使用实现了 InvocationHandler接口 的类作为代理对象的生产工厂, * 并且通过持有 被代理对象target,来在 invoke()方法 中对被代理对象的目标方法进行调用和增强, * 这些我们都能通过下面这段代码看懂,但代理对象是如何生成的?invoke()方法 又是如何被调用的呢? */publicclassProxyFactoryimplementsInvocationHandler { privateObjecttarget = null; publicObjectgetInstanse(Objecttarget){ this.target = target; returnProxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } @OverridepublicObjectinvoke(Objectproxy, Methodmethod, Object[] args) throwsThrowable { Objectret = null; System.out.println("前置增强"); ret = method.invoke(target, args); System.out.println("后置增强"); returnret; } } /** * 实现了 接口MyInterface 和接口的 play()方法,可以作为被代理类 */publicclassTargetObjectimplementsMyInterface { @Overridepublicvoidplay() { System.out.println("妲己,陪你玩 ~"); } } /** * 测试类 */publicclassProxyTest { publicstaticvoidmain(String[] args) { TargetObjecttarget = newTargetObject(); // ProxyFactory 实现了 InvocationHandler接口,其中的 getInstanse()方法 利用 Proxy类// 生成了 target目标对象 的代理对象,并返回;且 ProxyFactory 持有对 target 的引用,可以在// invoke() 中完成对 target 相应方法的调用,以及目标方法前置后置的增强处理ProxyFactoryproxyFactory = newProxyFactory(); // 这个 mi 就是 JDK 的 Proxy类 动态生成的代理类 $Proxy0 的实例,该实例中的方法都持有对// invoke()方法 的回调,所以当调用其方法时,就能够执行 invoke() 中的增强处理MyInterfacemi = (MyInterface) proxyFactory.getInstanse(target); // 这样可以看到 mi 的 Class 到底是什么System.out.println(mi.getClass()); // 这里实际上调用的就是 $Proxy0代理类 中对 play()方法 的实现,结合下面的代码可以看到// play()方法 通过 super.h.invoke() 完成了对 InvocationHandler对象(proxyFactory)中// invoke()方法 的回调,所以我们才能够通过 invoke()方法 实现对 target对象 方法的// 前置后置增强处理mi.play(); // 总的来说,就是在 invoke()方法 中完成 target目标方法 的调用,及前置后置增强,// JDK 动态生成的代理类中对 invoke()方法 进行了回调 } /** * 将 ProxyGenerator 生成的动态代理类的输出到文件中,利用反编译工具 luyten 等就可 * 以看到生成的代理类的源码咯,下面给出了其反编译好的代码实现 */@TestpublicvoidgeneratorSrc(){ byte[] bytesFile = ProxyGenerator.generateProxyClass("$Proxy0", TargetObject.class.getInterfaces()); FileOutputStreamfos = null; try{ Stringpath = System.getProperty("user.dir") + "\\$Proxy0.class"; Filefile = newFile(path); fos = newFileOutputStream(file); fos.write(bytesFile); fos.flush(); } catch (Exceptione){ e.printStackTrace(); } finally{ try { fos.close(); } catch (IOExceptione) { // TODO Auto-generated catch blocke.printStackTrace(); } } } } /** * Proxy 生成的代理类,可以看到,其继承了 Proxy,并且实现了 被代理类的接口MyInterface */publicfinalclass$Proxy0extendsProxyimplementsMyInterface { privatestaticMethodm1; privatestaticMethodm0; privatestaticMethodm3; privatestaticMethodm2; static { try { $Proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); $Proxy0.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])newClass[0]); // 实例化 MyInterface 的 play()方法$Proxy0.m3 = Class.forName("com.shuitu.test.MyInterface").getMethod("play", (Class<?>[])newClass[0]); $Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])newClass[0]); } catch (NoSuchMethodExceptionex) { thrownewNoSuchMethodError(ex.getMessage()); } catch (ClassNotFoundExceptionex2) { thrownewNoClassDefFoundError(ex2.getMessage()); } } public$Proxy0(finalInvocationHandlerinvocationHandler) { super(invocationHandler); } publicfinalvoidplay() { try { // 这个 h 其实就是我们调用 Proxy.newProxyInstance()方法 时传进去的 ProxyFactory对象(它实现了// InvocationHandler接口),该对象的 invoke()方法 中实现了对目标对象的目标方法的增强。// 看到这里,利用动态代理实现方法增强的实现原理就全部理清咯super.h.invoke(this, $Proxy0.m3, null); } catch (Error | RuntimeExceptionerror) { thrownewRuntimeException(); } catch (Throwablet) { thrownewUndeclaredThrowableException(t); } } publicfinalbooleanequals(finalObjecto) { try { return (boolean)super.h.invoke(this, $Proxy0.m1, newObject[] { o }); } catch (Error | RuntimeExceptionerror) { thrownewRuntimeException(); } catch (Throwablet) { thrownewUndeclaredThrowableException(t); } } publicfinalinthashCode() { try { return (int)super.h.invoke(this, $Proxy0.m0, null); } catch (Error | RuntimeExceptionerror) { thrownewRuntimeException(); } catch (Throwablet) { thrownewUndeclaredThrowableException(t); } } publicfinalStringtoString() { try { return (String)super.h.invoke(this, $Proxy0.m2, null); } catch (Error | RuntimeExceptionerror) { thrownewRuntimeException(); } catch (Throwablet) { thrownewUndeclaredThrowableException(t); } } }
close