From 79945b2eea9581aa341546e9d73ddd53cd6e64c5 Mon Sep 17 00:00:00 2001 From: AmyliaY <35298395+AmyliaY@users.noreply.github.com> Date: Sun, 17 Nov 2019 18:01:39 +0800 Subject: [PATCH] Add files via upload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 动态代理实现原理解析 --- .../JDK动态代理的实现原理解析.md | 177 ++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 docs/Spring/AOP/JDK动态代理的实现原理解析.md diff --git a/docs/Spring/AOP/JDK动态代理的实现原理解析.md b/docs/Spring/AOP/JDK动态代理的实现原理解析.md new file mode 100644 index 0000000..a1ca610 --- /dev/null +++ b/docs/Spring/AOP/JDK动态代理的实现原理解析.md @@ -0,0 +1,177 @@ +最近在看springAOP部分的源码,所以对JDK动态代理具体是如何实现的这件事产生了很高的兴趣,而且能从源码上了解这个原理的话,也有助于对spring-aop模块的理解。话不多说,上代码。 +```java +/** + * 一般会使用实现了InvocationHandler的类 作为代理对象的生产工厂, + * 并且通过持有被代理对象target,来在invoke()方法中对被代理对象的目标方法进行调用和增强, + * 这些我们都能通过下面这段代码看懂,但代理对象是如何生成的?invoke()方法又是如何被调用的呢? + */ +public class ProxyFactory implements InvocationHandler{ + + private Object target = null; + + public Object getInstanse(Object target){ + + this.target = target; + return Proxy.newProxyInstance(target.getClass().getClassLoader(), + target.getClass().getInterfaces(), this); + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + + Object ret = null; + System.out.println("前置增强"); + ret = method.invoke(target, args); + System.out.println("后置增强"); + return ret; + } +} + +/** + * 实现了接口MyInterface和接口的play()方法,可以作为被代理类 + */ +public class TargetObject implements MyInterface { + + @Override + public void play() { + System.out.println("妲己,陪你玩 ~"); + + } +} + +/** + * 测试类 + */ +public class ProxyTest { + + public static void main(String[] args) { + TargetObject target = new TargetObject(); + //ProxyFactory实现了InvocationHandler接口,其中的getInstanse()方法利用Proxy类帮助生成了 + //target目标对象的代理对象,并返回;且ProxyFactory持有对target的引用,可以在invoke()中完成对target相应方法 + //的调用,以及目标方法前置后置的增强处理 + ProxyFactory proxyFactory = new ProxyFactory(); + //这个mi就是JDK的Proxy类生成的代理类$Proxy0的对象,这个对象中的方法都持有对invoke()方法的回调 + //所以当调用其方法时,就能够执行invoke()中的增强处理 + MyInterface mi = (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目标方法的调用,及前置后置增强 + //然后通过生成的代理类完成对对invoke()的回调 + } + + /** + * 将ProxyGenerator生成的动态代理类的输出到文件中,利用反编译工具luyten等就可 + * 以看到生成的代理类的源码咯,下面给出了其反编译好的代码实现 + */ + @Test + public void generatorSrc(){ + byte[] bytesFile = ProxyGenerator.generateProxyClass("$Proxy0", TargetObject.class.getInterfaces()); + FileOutputStream fos = null; + try{ + String path = System.getProperty("user.dir") + "\\$Proxy0.class"; + File file = new File(path); + fos = new FileOutputStream(file); + fos.write(bytesFile); + fos.flush(); + } catch (Exception e){ + e.printStackTrace(); + } finally{ + try { + fos.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } +} + +/** + * Proxy生成的代理类,可以看到,其继承了Proxy,并且实现了被代理类的接口 + */ +public final class $Proxy0 extends Proxy implements MyInterface +{ + private static Method m1; + private static Method m0; + private static Method m3; + private static Method m2; + + 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[])new Class[0]); + //实例化MyInterface的play方法 + $Proxy0.m3 = Class.forName("com.shuitu.test.MyInterface").getMethod("play", (Class[])new Class[0]); + $Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class[])new Class[0]); + } + catch (NoSuchMethodException ex) { + throw new NoSuchMethodError(ex.getMessage()); + } + catch (ClassNotFoundException ex2) { + throw new NoClassDefFoundError(ex2.getMessage()); + } + } + + public $Proxy0(final InvocationHandler invocationHandler) { + super(invocationHandler); + } + + public final void play() { + try { + //这个h其实就是我们调用Proxy.newProxyInstance()方法时传进去的ProxyFactory对象, + //该对象的invoke()方法中实现了对目标对象的目标方法的增强。看到这里,利用动态代理实现方法增强的 + //调用原理就全部理清咯 + super.h.invoke(this, $Proxy0.m3, null); + } + catch (Error | RuntimeException error) { + throw new RuntimeException(); + } + catch (Throwable t) { + throw new UndeclaredThrowableException(t); + } + } + + public final boolean equals(final Object o) { + try { + return (boolean)super.h.invoke(this, $Proxy0.m1, new Object[] { o }); + } + catch (Error | RuntimeException error) { + throw new RuntimeException(); + } + catch (Throwable t) { + throw new UndeclaredThrowableException(t); + } + } + + public final int hashCode() { + try { + return (int)super.h.invoke(this, $Proxy0.m0, null); + } + catch (Error | RuntimeException error) { + throw new RuntimeException(); + } + catch (Throwable t) { + throw new UndeclaredThrowableException(t); + } + } + + public final String toString() { + try { + return (String)super.h.invoke(this, $Proxy0.m2, null); + } + catch (Error | RuntimeException error) { + throw new RuntimeException(); + } + catch (Throwable t) { + throw new UndeclaredThrowableException(t); + } + } + +} + +```