jdk动态代理实现原理
程序员文章站
2022-03-10 13:00:43
...
jdk的动态代理即使用反射来实现,具体由Proxy、InvocationHandler等类来实现的。
具体调用过程比较难理解,但是如果看到生成的代理类就不难理解了。
代码如下:
接口类:Calculator.java
实现类:CalculatorImpl.java
代理类:CalculatorProxy.java
测试代码:TestProxy.java
反编译proxy.class得到的java代码如下:
因此,调用proxy.add(2,3),实际上就是调用LogHandler的invoke方法
具体调用过程比较难理解,但是如果看到生成的代理类就不难理解了。
代码如下:
接口类:Calculator.java
package com.yangjianzhou.javaBasics; /** * Created by yangjianzhou on 16-5-8. */ public interface Calculator { public int add(int operator1 , int operator2); }
实现类:CalculatorImpl.java
package com.yangjianzhou.javaBasics; /** * Created by yangjianzhou on 16-5-8. */ public class CalculatorImpl implements Calculator { @Override public int add(int operator1, int operator2) { System.out.println("operator1 + operator2 = " + (operator1 + operator2)); return operator1 + operator2; } }
代理类:CalculatorProxy.java
package com.yangjianzhou.javaBasics; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * Created by yangjianzhou on 16-5-8. */ public class CalculatorProxy { public void executeProxy(){ Calculator calculator = new CalculatorImpl(); LogHandler logHandler = new LogHandler(calculator); Calculator proxy = (Calculator) Proxy.newProxyInstance(calculator.getClass().getClassLoader() , calculator.getClass().getInterfaces(),logHandler); proxy.add(2,3); } } class LogHandler implements InvocationHandler{ Object obj ; public LogHandler(Object obj) { this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { this.doBefore(); Object object = method.invoke(obj , args); this.doAfter(); return object; } public void doBefore(){ System.out.println("log before method"); } public void doAfter(){ System.out.println("log after method"); } }
测试代码:TestProxy.java
package com.yangjianzhou.javaBasics; import sun.misc.ProxyGenerator; import java.io.FileOutputStream; /** * Created by yangjianzhou on 16-5-8. */ public class TestProxy { public static void main(String[] args) throws Exception { CalculatorProxy calculatorProxy = new CalculatorProxy(); calculatorProxy.executeProxy(); byte[] classCode = ProxyGenerator.generateProxyClass("com.yangjianzhou.javaBasics.", new Class[]{Calculator.class}); FileOutputStream fileOutputStream = new FileOutputStream("/tmp/proxy.class"); fileOutputStream.write(classCode); fileOutputStream.close(); } }
反编译proxy.class得到的java代码如下:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.yangjianzhou.javaBasics; import com.yangjianzhou.javaBasics.Calculator; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class extends Proxy implements Calculator { private static Method m1; private static Method m0; private static Method m3; private static Method m2; public (InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue(); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final int hashCode() throws { try { return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue(); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int add(int var1, int var2) throws { try { return ((Integer)super.h.invoke(this, m3, new Object[]{Integer.valueOf(var1), Integer.valueOf(var2)})).intValue(); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")}); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m3 = Class.forName("com.yangjianzhou.javaBasics.Calculator").getMethod("add", new Class[]{Integer.TYPE, Integer.TYPE}); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
因此,调用proxy.add(2,3),实际上就是调用LogHandler的invoke方法
上一篇: mysql explain的使用及理解