JDK代理

public class JdkProxyDemo { interface Foo { void foo(); } static final class Target implements Foo { public void foo() { System.out.println("target foo"); } } // jdk 只能针对接口代理 // cglib public static void main(String[] param) throws IOException { // 目标对象 Target target = new Target(); ClassLoader loader = JdkProxyDemo.class.getClassLoader(); // 用来加载在运行期间动态生成的字节码 Foo proxy = (Foo) Proxy.newProxyInstance(loader, new Class[]{Foo.class}, (p, method, args) -> { System.out.println("before..."); // 目标.方法(参数) // 方法.invoke(目标, 参数); Object result = method.invoke(target, args); System.out.println("after...."); return result; // 让代理也返回目标方法执行的结果 }); System.out.println(proxy.getClass()); proxy.foo(); System.in.read(); } }
notion image
public class JdkProxyDemo { interface Foo { void foo2(); void foo(); } static final class Target implements Foo { @Override public void foo2() { System.out.println("target foo2"); } public void foo() { System.out.println("target foo"); } }
调用proxy.foo2();
// cglib public static void main(String[] param) throws IOException { // 目标对象 Target target = new Target(); ClassLoader loader = JdkProxyDemo.class.getClassLoader(); // 用来加载在运行期间动态生成的字节码 Foo proxy = (Foo) Proxy.newProxyInstance(loader, new Class[]{Foo.class}, (p, method, args) -> { System.out.println("before..."); // 目标.方法(参数) // 方法.invoke(目标, 参数); Object result = method.invoke(target, args); System.out.println("after...."); return result; // 让代理也返回目标方法执行的结果 }); System.out.println(proxy.getClass()); proxy.foo2(); System.in.read(); }
 
class com.onethink.a11.$Proxy0 before... target foo2 after....

原理

jdk使用ASM字节码框架动态生成代理对象的字节码文件,加载到jvm

模拟jdk代理

public class A12 { interface Foo { void foo(); int bar(); } static class Target implements Foo { public void foo() { System.out.println("target foo"); } public int bar() { System.out.println("target bar"); return 100; } } public static void main(String[] param) { // ⬇️1. 创建代理,这时传入 InvocationHandler Foo proxy = new $Proxy0(new InvocationHandler() { // ⬇️5. 进入 InvocationHandler public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ // ⬇️6. 功能增强 System.out.println("before..."); // ⬇️7. 反射调用目标方法 return method.invoke(new Target(), args); } }); // ⬇️2. 调用代理方法 proxy.foo(); proxy.bar(); } }
 

模拟代理类

  1. 继承Proxy类,将InvocationHandler的实例作为组合对象构造传入
  1. 实现Foo类接口,覆写foo() 方法,调用组合的InvocationHandler实例对象的invoke方法
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; // ⬇️这就是 jdk 代理类的源码, 秘密都在里面 public class $Proxy0 extends Proxy implements A12.Foo { public $Proxy0(InvocationHandler h) { super(h); } // ⬇️3. 进入代理方法 public void foo() { try { // ⬇️4. 回调 InvocationHandler h.invoke(this, foo, new Object[0]); } catch (RuntimeException | Error e) { throw e; } catch (Throwable e) { throw new UndeclaredThrowableException(e); } } @Override public int bar() { try { Object result = h.invoke(this, bar, new Object[0]); return (int) result; } catch (RuntimeException | Error e) { throw e; } catch (Throwable e) { throw new UndeclaredThrowableException(e); } } static Method foo; static Method bar; static { try { foo = A12.Foo.class.getMethod("foo"); bar = A12.Foo.class.getMethod("bar"); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); } } }
 

jdk代理字节码生成

Arthas动态获取代理类

启动Arthas
java -jar .\arthas-boot.jar
notion image
选择JdkProxyDemo这个进程实例
反编译生成的动态代理类
jad com.onethink.a11.$Proxy0
notion image
notion image
notion image
notion image
notion image

ASM动态生成方式

idea安装ASM Bytecode Viewer 插件
右键点击自己编写的$proxy0类,点击ASM Bytecode Viewer
notion image
将生成的$Proxy0Dump复制出来,asm替换为spring的asm
public class TestProxy { public static void main(String[] args) throws Exception { byte[] dump = $Proxy0Dump.dump(); /*FileOutputStream os = new FileOutputStream("$Proxy0.class"); os.write(dump, 0, dump.length); os.close();*/ ClassLoader loader = new ClassLoader() { @Override protected Class<?> findClass(String name) throws ClassNotFoundException { return super.defineClass(name, dump, 0, dump.length); } }; Class<?> proxyClass = loader.loadClass("com.onethink.$Proxy0"); Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class); Foo proxy = (Foo) constructor.newInstance(new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before..."); System.out.println("调用目标"); return null; } }); proxy.foo(); } }
notion image

jdk方法反射优化

 
// 运行时请添加 --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/jdk.internal.reflect=ALL-UNNAMED public class TestMethodInvoke { public static void main(String[] args) throws Exception { //循环17次验证反射优化 Method foo = TestMethodInvoke.class.getMethod("foo", int.class); for (int i = 1; i <= 17; i++) { show(i, foo); foo.invoke(null, i); } System.in.read(); } // 方法反射调用时, 底层 MethodAccessor 的实现类 private static void show(int i, Method foo) throws Exception { Method getMethodAccessor = Method.class.getDeclaredMethod("getMethodAccessor"); getMethodAccessor.setAccessible(true); Object invoke = getMethodAccessor.invoke(foo); if (invoke == null) { System.out.println(i + ":" + null); return; } Field delegate = Class.forName("jdk.internal.reflect.DelegatingMethodAccessorImpl").getDeclaredField("delegate"); delegate.setAccessible(true); System.out.println(i + ":" + delegate.get(invoke)); } public static void foo(int i) { System.out.println(i + ":" + "foo"); } }
JDK的代理会针对每个方法生成一个代理类NativeMethodAccessorImpl代理类,这个代理类会调本地方法
调用超过17次的时候新生成一个
1:null 1:foo 2:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 2:foo 3:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 3:foo 4:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 4:foo 5:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 5:foo 6:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 6:foo 7:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 7:foo 8:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 8:foo 9:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 9:foo 10:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 10:foo 11:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 11:foo 12:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 12:foo 13:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 13:foo 14:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 14:foo 15:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 15:foo 16:jdk.internal.reflect.NativeMethodAccessorImpl@3d494fbf 16:foo 17:jdk.internal.reflect.GeneratedMethodAccessor2@5e9f23b4 17:foo
NativeMethodAccessorImpl通过 jad jdk.internal.reflect.NativeMethodAccessorImpl
notion image
 
GeneratedMethodAccessor2通过 arthas 反编译 jad jdk.internal.reflect.GeneratedMethodAccessor2
notion image