動態代理的實現
阿新 • • 發佈:2022-02-13
代理
所謂代理就是給一個不具有某個功能的類增加某個目標類的功能,如下,被代理類LogHandler 增加一個Calculator 的add方法
//介面 package gn.k48.proxy; public interface Calculator { int add(int a, int b); } //實現類 package gn.k48.proxy; public class CalculatorImpl implements Calculator { @Override public int add(int a, int b) { System.out.println(a + b); return a + b; } } //被代理目標類 package gn.k48.proxy; import sun.misc.ProxyGenerator; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class LogHandler implements InvocationHandler { Object object; public LogHandler(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { this.doBefore(); Object o = method.invoke(object, args); this.doAfter(); return o; } public void doBefore() { System.out.println("do this before"); } public void doAfter() { System.out.println("do this after"); } public static void main(String[] args) throws IOException { Calculator calculator = new CalculatorImpl(); LogHandler logHandler = new LogHandler(calculator); Calculator proxy = (Calculator) Proxy.newProxyInstance( calculator.getClass().getClassLoader(), calculator.getClass().getInterfaces(), logHandler); byte[] bs = ProxyGenerator.generateProxyClass("Calculator", new Class[]{proxy.getClass()}); FileOutputStream fos = new FileOutputStream("../Calculator.class"); fos.write(bs); proxy.add(1, 2); } }
打印出通過Proxy.newProxyInstance生成的動態類class檔案
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // import com.sun.proxy..Proxy0; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class Calculator extends Proxy implements Proxy0 { private static Method m1; private static Method m6; private static Method m2; private static Method m7; private static Method m11; private static Method m13; private static Method m0; private static Method m8; private static Method m12; private static Method m3; //add private static Method m5; private static Method m10; private static Method m4; private static Method m9; public Calculator(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final InvocationHandler getInvocationHandler(Object var1) throws IllegalArgumentException { try { return (InvocationHandler)super.h.invoke(this, m6, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } 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); } } public final Class getProxyClass(ClassLoader var1, Class[] var2) throws IllegalArgumentException { try { return (Class)super.h.invoke(this, m7, new Object[]{var1, var2}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final Class getClass() throws { try { return (Class)super.h.invoke(this, m11, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void notifyAll() throws { try { super.h.invoke(this, m13, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void wait() throws InterruptedException { try { super.h.invoke(this, m8, (Object[])null); } catch (RuntimeException | InterruptedException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void notify() throws { try { super.h.invoke(this, m12, (Object[])null); } 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[]{var1, var2}); } catch (RuntimeException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final Object newProxyInstance(ClassLoader var1, Class[] var2, InvocationHandler var3) throws IllegalArgumentException { try { return (Object)super.h.invoke(this, m5, new Object[]{var1, var2, var3}); } catch (RuntimeException | Error var5) { throw var5; } catch (Throwable var6) { throw new UndeclaredThrowableException(var6); } } public final void wait(long var1) throws InterruptedException { try { super.h.invoke(this, m10, new Object[]{var1}); } catch (RuntimeException | InterruptedException | Error var4) { throw var4; } catch (Throwable var5) { throw new UndeclaredThrowableException(var5); } } public final boolean isProxyClass(Class var1) throws { try { return (Boolean)super.h.invoke(this, m4, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final void wait(long var1, int var3) throws InterruptedException { try { super.h.invoke(this, m9, new Object[]{var1, var3}); } catch (RuntimeException | InterruptedException | Error var5) { throw var5; } catch (Throwable var6) { throw new UndeclaredThrowableException(var6); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m6 = Class.forName("com.sun.proxy.$Proxy0").getMethod("getInvocationHandler", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m7 = Class.forName("com.sun.proxy.$Proxy0").getMethod("getProxyClass", Class.forName("java.lang.ClassLoader"), Class.forName("[Ljava.lang.Class;")); m11 = Class.forName("com.sun.proxy.$Proxy0").getMethod("getClass"); m13 = Class.forName("com.sun.proxy.$Proxy0").getMethod("notifyAll"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); m8 = Class.forName("com.sun.proxy.$Proxy0").getMethod("wait"); m12 = Class.forName("com.sun.proxy.$Proxy0").getMethod("notify"); m3 = Class.forName("com.sun.proxy.$Proxy0").getMethod("add", Integer.TYPE, Integer.TYPE); m5 = Class.forName("com.sun.proxy.$Proxy0").getMethod("newProxyInstance", Class.forName("java.lang.ClassLoader"), Class.forName("[Ljava.lang.Class;"), Class.forName("java.lang.reflect.InvocationHandler")); m10 = Class.forName("com.sun.proxy.$Proxy0").getMethod("wait", Long.TYPE); m4 = Class.forName("com.sun.proxy.$Proxy0").getMethod("isProxyClass", Class.forName("java.lang.Class")); m9 = Class.forName("com.sun.proxy.$Proxy0").getMethod("wait", Long.TYPE, Integer.TYPE); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
可以看到生成的位元組碼是一個Proxy的子類,將在add方法中呼叫了Proxy的m3方法
I'm a fucKing fake coder!