zoukankan      html  css  js  c++  java
  • java 动态代理

    0x01 描述

    ”动态代理中的动态,是针对使用java代码实际编写了代理类的“静态”代理而言的,它的优势不在于省去了编写代理类的那一点工作量,而是实现了可以在原始类和接口还未知的时候,就可以确定代理类的行为,当代理类与原始类脱离直接联系后,就可以很灵活地重用于不同的应用场景中"  引自 《深入理解java虚拟机 java高级特性与最佳实践》。

    它的缺点:因为java中类只支持单继承,而代理类有个共同的父类Proxy,所有注定了动态代理不能为类成员方法作代理的缺陷。

    0x02 demo

    package test;
    public interface IWorker {
        Object work(Object... objects);
    }
    package test;
    
    public class Worker implements IWorker {
    
        @Override
        public Object work(Object... objects) {
            System.out.println("Working ...");
            return "work method";
        }
    }
    package test;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class Handler implements InvocationHandler {
        IWorker mWorker;
    
        Handler(IWorker iWorker) {
            this.mWorker = iWorker;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            if (method.getName().equals("equals")) {
                System.out.println("the equals method will always return true");
                return true;
            } else if (method.getName().equals("hashCode")) {
                System.out.println("yes, the hashCode is ");
            } else if (method.getName().equals("toString")) {
                System.out.println("toString method has been called");
            }
            return method.invoke(mWorker, args);
        }
    
    }
    package test;
    
    import java.lang.reflect.Proxy;
    
    public class Test {
        public static void main(String[] args) {
            System.getProperties().put(
                    "sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
            IWorker worker = (IWorker) Proxy.newProxyInstance(
                    IWorker.class.getClassLoader(), Worker.class.getInterfaces(),
                    new Handler(new Worker()));
            System.out.println(worker.work());
            System.out.println(worker.equals(null));
            System.out.println(worker.toString());
            System.out.println(worker.hashCode());
        }
    }

    0x03 动态生成的代理类的代码

    package com.sun.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    import test.IWorker;
    
    public final class $Proxy0
      extends Proxy
      implements IWorker
    {
      private static Method m1;
      private static Method m2;
      private static Method m3;
      private static Method m0;
      
      public $Proxy0(InvocationHandler paramInvocationHandler)
        throws 
      {
        super(paramInvocationHandler);
      }
      
      public final boolean equals(Object paramObject)
        throws 
      {
        try
        {
          return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final String toString()
        throws 
      {
        try
        {
          return (String)this.h.invoke(this, m2, null);
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final Object work(Object[] paramArrayOfObject)
        throws 
      {
        try
        {
          return (Object)this.h.invoke(this, m3, new Object[] { paramArrayOfObject });
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      public final int hashCode()
        throws 
      {
        try
        {
          return ((Integer)this.h.invoke(this, m0, null)).intValue();
        }
        catch (Error|RuntimeException localError)
        {
          throw localError;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
      
      static
      {
        try
        {
          m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
          m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
          m3 = Class.forName("test.IWorker").getMethod("work", new Class[] { Class.forName("[Ljava.lang.Object;") });
          m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
          return;
        }
        catch (NoSuchMethodException localNoSuchMethodException)
        {
          throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
        }
        catch (ClassNotFoundException localClassNotFoundException)
        {
          throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
        }
      }
    }

     0x04 注意

    1、动态生成的方法都是final的

    2、除了接口中的方法外,默认它还覆盖了Object类中的toString、hashCode和equals方法

    3、每个方法都进行了异常的捕捉,虽然对异常进行了简单的分类处理,但是仍然使用了奇怪的语法将捕捉到的运行时异常照常抛出,所以在使用到代理类的地方照样可以使用正常的异常出来逻辑来处理运行时抛出的异常

  • 相关阅读:
    集中式(SVN)和分布式(Git)版本控制系统的简单比较
    Mac 提示安装包已损坏
    React 获取 url 参数 —— this.props.match
    编写一个 Chrome 浏览器扩展程序
    webpack 配置学习笔记
    Python 进阶学习笔记
    Python 入门学习笔记
    (转)Unity3d各种坑
    unity3d 网页游戏客户端工程构建方案
    (转)在Unity3D的网络游戏中实现资源动态加载
  • 原文地址:https://www.cnblogs.com/LuLei1990/p/4593737.html
Copyright © 2011-2022 走看看