美文网首页
Java动态代理

Java动态代理

作者: pphdsny | 来源:发表于2017-10-31 09:34 被阅读22次

    Java动态代理

    简要说明

    在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class)。

    InvocationHandler

    每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用 一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:

    // proxy: 指代我们所代理的那个真实对象
    // method: 指代的是我们所要调用真实对象的方法的Method对象
    // args: 指代的是调用真实对象某个方法时接受的参数
    // 返回的Object是指真实对象方法的返回类型
    
    Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    

    Proxy

    Proxy这个类的作用就是用来动态创建一个代理对象

    // 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
    loader - the class loader to define the proxy class  
    // 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口
    interfaces - the list of interfaces for the proxy class to implement 
    // 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
    h - the invocation handler to dispatch method invocations to 
    Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
    

    示例

    具体可参考 http://www.jianshu.com/p/e63b0685e8e

    具体接口的生成类$Proxy0.class默认是不保存的,如需看到,可使用如下方法

    /* 设置此系统属性,让JVM生成的Proxy类写入文件.保存路径为:com/sun/proxy(如果不存在请手工创建) */  
    System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");  
    

    �生成的代理类$Proxy0如下

    public final class $Proxy0 extends Proxy implements IPerson {
        private static Method m1;
        private static Method m3;
        private static Method m4;
        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})).booleanValue();
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }
    
        public final String getName() 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 getNameById(int var1) throws  {
            try {
                return (String)super.h.invoke(this, m4, new Object[]{Integer.valueOf(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 int hashCode() throws  {
            try {
                return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        static {
            try {
                m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
                m3 = Class.forName("com.example.proxy.IPerson").getMethod("getName", new Class[0]);
                m4 = Class.forName("com.example.proxy.IPerson").getMethod("getNameById", new Class[]{Integer.TYPE});
                m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
                m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            } catch (NoSuchMethodException var2) {
                throw new NoSuchMethodError(var2.getMessage());
            } catch (ClassNotFoundException var3) {
                throw new NoClassDefFoundError(var3.getMessage());
            }
        }
    }
    

    Retrofit的动态代理实现

      public <T> T create(final Class<T> service) {
        Utils.validateServiceInterface(service);
        if (validateEagerly) {
          eagerlyValidateMethods(service);
        }
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
            new InvocationHandler() {
              private final Platform platform = Platform.get();
    
              @Override public Object invoke(Object proxy, Method method, Object[] args)
                  throws Throwable {
                // If the method is a method from Object then defer to normal invocation.
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                if (platform.isDefaultMethod(method)) {
                  return platform.invokeDefaultMethod(method, service, proxy, args);
                }
                //Retrofit并没有将实例传递进来,而是通过注解生成具体的方法调用
                //TODO 方法生成代码待分析
                ServiceMethod<Object, Object> serviceMethod =
                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
                OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
                return serviceMethod.callAdapter.adapt(okHttpCall);
              }
            });
      }
    

    相关文章

      网友评论

          本文标题:Java动态代理

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