美文网首页
动态代理源码解析

动态代理源码解析

作者: Pimow | 来源:发表于2018-11-24 18:06 被阅读0次

    什么是代理模式

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


    image.png

    jdk动态代理demo

     public interface Interview {
              String result();
      }
     public class InterviewImpl implements  Interview {
        @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代理是生成一个代理接口的代理类。

    相关文章

      网友评论

          本文标题:动态代理源码解析

          本文链接:https://www.haomeiwen.com/subject/lhdyqqtx.html