vlambda博客
学习文章列表

深入Java动态代理源码

背景介绍

什么是动态代理?
动态代理,本质上还是代理模式,只不过代理类是在JDK内部产生并创建实例(字节码编辑)。再者其内部还维护了一个基于弱引用的缓存结构。总结来说:动态代理 = 代理模式 + 字节码编辑 + 弱引用缓存。

我们来探究一下这个过程。

原理探究

示例代码:

public class TestProxy { interface Hello { void hello(); }
private static class HelloImpl implements Hello { @Override public void hello() { System.out.println("hello"); } }
public static void main(String[] args) { Hello hello = new HelloImpl(); Class<? extends Hello> clazz = hello.getClass();
Hello proxy = (Hello)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // String name = method.getName(); if ("hello".equals(name)) { // System.out.println("xxx"); } return null; } }); proxy.hello(); }}


调用关系:

弱引用WeakReference

WeakCache基于弱引用的缓存结构。
构造如下:

public WeakCache(BiFunction<K, P, ?> subKeyFactory, BiFunction<K, P, V> valueFactory) { this.subKeyFactory = Objects.requireNonNull(subKeyFactory); this.valueFactory = Objects.requireNonNull(valueFactory);}

其中的subKeyFactory为Proxy.KeyFactory;valueFactory为Proxy.ProxyClassFactory。二者都实现了BiFunction接口,简单工厂的实现。

核心数据结构:

private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap<>();

两层Map的结构:
第一层的key:CacheKey类型,继承WeakReference,使用其valueOf()创建实例(简单工厂模式)。
第一层的value:Map结构,即第二层。

第二层的key:类型可以为:Key1 Key2 KeyN 和Object(key0),不一定会继承WeakReference。通过subKeyFactory创建对象。
第二层的value:CacheValue类型,继承WeakReference,使用构造方法创建,参数为valueFactory创建的对象。

简单工厂+函数接口

Proxy.KeyFactory和Proxy.ProxyClassFactory都是简单工厂,分别用于创建key和value对象;其实现BiFunction接口,以BiFunction的apply()作为工厂的方法。

字节码编辑技术

ProxyGenerator#generateProxyClass()是基于字节码编辑技术直接产生字节码,我我们可以通过如下代码,反编译查看一下生成的class文件的源代码:

测试代码:

byte[] bytes = ProxyGenerator.generateProxyClass("xxx$Proxy", clazz.getInterfaces(), 16);Path path = Paths.get("/Users/xwei/Desktop/Proxy.class");try { Files.createFile(path); OutputStream outputStream = Files.newOutputStream(path, StandardOpenOption.WRITE); outputStream.write(bytes); outputStream.close();} catch (IOException e) { e.printStackTrace();}

反编译之后的代理类的源代码:

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//
import com.proxy.TestProxy.Hello;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;
final class xxx$Proxy extends Proxy implements Hello { private static Method m1; private static Method m3; private static Method m2; private static Method m0;
public xxx$Proxy(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 void hello() throws { try { super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } }
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 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); } }
static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m3 = Class.forName("com.proxy.TestProxy$Hello").getMethod("hello"); m2 = Class.forName("java.lang.Object").getMethod("toString"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } }}