动态代理源码解析

什么是代理模式
代理模式即 Proxy Pattern。代理模式为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

动态代理源码解析
文章图片
image.png jdk动态代理demo

public interface Interview { String result(); } public class InterviewImpl implementsInterview { @Override public String result() { System.out.println("真正想要面试的人。"); return "ok"; } } public class ProxyHandler implements InvocationHandler { private InterviewImpl interview; public ProxyHandler(InterviewImpl interview) { this.interview = interview; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("准备面试"); Object invoke = method.invoke(interview, args); System.out.println("准备结束"); return invoke; } public static void main(String[] args) { //会在项目的根目录生成com.sun.proxy生成$parxo0.class System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); InterviewImpl interview = new InterviewImpl(); //这里也可以使用Proxy.getProxyClass().getConstructor()获取代理对象 //这里获取的是被代理对象,并不是目标对象 Interview o = (Interview) Proxy.newProxyInstance(ProxyHandler.class.getClassLoader(), new Class[]{Interview.class},new ProxyHandler(interview)); String result = o.result(); } }

从上面这个demo我们可以看出,只是直接调用面试对象,而是通过动态代理调用面试对象。
生成的代理对象 【动态代理源码解析】我们可以看出生成代理对象类名是$Proxy+数字
代理对象代理了接口本身的方法,同时也代理啦toString(),equals(),hashcode()。
public final class $Proxy0 extends Proxy implements Interview { private static Method m1; private static Method m3; private static Method m2; private static Method m0; public $Proxy0(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 String result() throws{ try { return (String)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.amos.study.base.java.proxy.dynamic.Interview").getMethod("result"); 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()); } } }

JDK动态代理源码解析
我真的不知道改怎么去描述代码。首先调用getProxyClass0(loader, intfs)得到代理类。线程proxyClassCache缓存中获取,不存在则创建Factory,从Factory中组装代理对象,代理对象的包名com.sun.proxy+$Proxy+AtomicLong。然后通过 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags); 生成字节码。调用defineClass0()将字节码写入类文件中。cl.getConstructor(constructorParams)返回带有实现InvocationHandler接口的构造器。其实这里就找到了代理类。jdk代理是生成一个代理接口的代理类。

    推荐阅读