Java動態代理

通過以下幾種方式介紹動態代理

  • 動態代理涉及到的類
  • 動態代理用法
  • Proxy類解析
  • 動態代理類解析
動態代理涉及到的類
InvocationHandler(Interface)// 處理類
    //參數-> 代理類對象,被代理類的方法,被代理類方法參數(MyInvocationHandler 類中有印證)
    //返回值-> 被代理類方法返回結果
    public Object invoke(Object proxy, Method method, Object[] args)
 
Proxy(Class)// 動態創建一個代理對象的類
     // 參數->類加載器,被代理類實現的接口,InvocationHandler 實現類
     // 返回值->代理類(動態生成)
     public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
     // 參數->類加載器,被代理類實現的接口
     // 返回值->未被實例化的代理類(構造器參數類型為InvocationHandler)
     public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces)
動態代理用法
public class Test {

public static void main(String[] args) throws Exception{
    proxyTest1();// 方法一
    proxyTest2();// 方法二
}

// 動態代理方法一
private static void proxyTest1() {
    // 創建訂單方法
    OrderInterface order = new OrderService();

    InvocationHandler invocationHandler = getInvocationHandler(order);

    /**
     * Proxy.newProxyInstance 方法三個參數
     *  ClassLoader loader 類加載器
     *  Class<?>[] interfaces 訂單類接口
     *  InvocationHandler h 處理器(內含增強方法-打印處理訂單日志)
     *
     *  通過類加載器和訂單類接口動態創建代理類,
     *  然后將處理器設置進動態代理類,
     *  返回實現訂單類接口的動態代理實現類(動態生成)
     *
     * */
    OrderInterface orderInterface = (OrderInterface)Proxy.newProxyInstance(order.getClass().getClassLoader(), order.getClass().getInterfaces(), invocationHandler);

    orderInterface.createOrder(new OrderInfo());
}
// 動態代理方法二
private static void proxyTest2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    // 創建訂單方法
    OrderInterface order = new OrderService();

    InvocationHandler invocationHandler = getInvocationHandler(order);
    /**
     * ClassLoader loader 類加載器
     * Class<?>... interfaces 訂單類接口
     *
     * 通過類加載器和訂單類接口動態創建代理類
     * */
    Class<?> clazz = Proxy.getProxyClass(order.getClass().getClassLoader(), order.getClass().getInterfaces());
    /**
     * 獲取參數為InvocationHandler類型的構造器
     * */
    Constructor constructor = clazz.getConstructor(InvocationHandler.class);
    /**
     * 將處理器傳進參數里,實例化類,進行調用以達到增強方法的目的
     * */
    OrderInterface orderInterface = (OrderInterface)constructor.newInstance(invocationHandler);

    orderInterface.createOrder(new OrderInfo());
}

// InvocationHandler 處理器
private static InvocationHandler getInvocationHandler(OrderInterface order) {
    // 內部實現InvocationHandler接口,增強被代理類方法功能
    InvocationHandler invocationHandler = new MyInvocationHandler(order);
    return invocationHandler;
}
}

處理類

public class MyInvocationHandler implements InvocationHandler {

  private Object object;

  public MyInvocationHandler(Object object) {
      this.object = object;
  }

   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(new StringBuilder("Object proxy-->className:").append(proxy.getClass().getName()));
        System.out.println(new StringBuilder("Method method-->methodName:").append(method.getName()));
        if (null != args && args.length > 0) {
            System.out.println(new StringBuilder("Object[] args-->paramValue:").append(args[0].toString()));
        }

         System.out.println(new StringBuilder("增強方法:").append("記錄日志...").toString());

         Object returnObject = method.invoke(object, args);

         return returnObject;
   }
}

訂單類接口

 public interface OrderInterface {
   public void createOrder(OrderInfo order);
}

訂單處理類(執行下單流程)

public class OrderService implements OrderInterface {

  public void createOrder(OrderInfo order) {
    System.out.print("創建訂單");

    try {
        for (int i = 0; i < 3; i++) {
            Thread.sleep(500);
            System.out.print(".");
        }

    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("");
    System.out.println("訂單創建成功");
}
}

實體類

public class OrderInfo {
     @Override
     public String toString() {
         return "ClassName-->OrderInfo";
      }
}
Proxy類解析

屬性及構造器

// 構造器參數類型
private static final Class<?>[] constructorParams = { InvocationHandler.class };
// 代理類緩存,采用弱引用方式進行緩存,方便jvm進行gc垃圾回收
private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
// 處理類,通過構造器進行賦值。1:子類繼承Proxy類,構造器賦值,2:Proxy.newProxyInstance()調用該方法生成代理類,利用反射創建代理類進行構造器賦值
protected InvocationHandler h;
// 提供的兩種構造器限制了我們使用Proxy類只能直接調用靜態方法
private Proxy() {
}
// 創建動態代理類會使用到該構造器
protected Proxy(InvocationHandler h) {
    this.h = h;
}

方法

// 獲取代理類(在文章開頭有介紹此方法)。
public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)  throws IllegalArgumentException
{
    final Class<?>[] intfs = interfaces.clone();
    final SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
    }
    // 獲取代理類
    return getProxyClass0(loader, intfs);
}

// 獲取代理類,并且生成代理類實例(在文章開頭有介紹此方法)。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
{
   // 代碼和getProxyClass方法目的一致,獲取動態代理類。
    -------------------------------------------------------------------------
    Objects.requireNonNull(h);
    final Class<?>[] intfs = interfaces.clone();
    final SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
    }
    Class<?> cl = getProxyClass0(loader, intfs);
    -------------------------------------------------------------------------
    try {
        if (sm != null) {
            checkNewProxyPermission(Reflection.getCallerClass(), cl);
        }
        // 通過反射獲取參數為InvocationHandler類型的構造器
        final Constructor<?> cons = cl.getConstructor(constructorParams);
        final InvocationHandler ih = h;
       
        if (!Modifier.isPublic(cl.getModifiers())) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    cons.setAccessible(true);
                    return null;
                }
            });
        }
        // 實例化動態代理類,并指定構造器參數
        return cons.newInstance(new Object[]{h});
    } catch (IllegalAccessException|InstantiationException e) {
        throw new InternalError(e.toString(), e);
    } catch (InvocationTargetException e) {
        Throwable t = e.getCause();
        if (t instanceof RuntimeException) {
            throw (RuntimeException) t;
        } else {
            throw new InternalError(t.toString(), t);
        }
    } catch (NoSuchMethodException e) {
        throw new InternalError(e.toString(), e);
    }
}  

// 生成動態代理類
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) {
    if (interfaces.length > 65535) {
        throw new IllegalArgumentException("interface limit exceeded");
    }

    // 代理類的獲取及創建(使用了弱引用方式)
    return proxyClassCache.get(loader, interfaces);
}
動態代理類解析(生成代理類方法在git中)
// ProxyObject 隨意指定的一個類名,該類繼承了Proxy(構造賦值),實現了OrderInterface接口(實現代理方法)
public final class ProxyObject extends Proxy implements 
{
  private static Method m1;
  private static Method m3;
  private static Method m2;
  private static Method m0;
  // 代理類構造,參數為InvocationHandler 類型。上文介紹了,Proxy 類InvocationHandler 賦值第一種方式:子類繼承Proxy類,構造器賦值
  public ProxyObject(InvocationHandler paramInvocationHandler)
  {
    super(paramInvocationHandler);
  }

  static
   {
     try
     {
       // 反射生成方法內所有方法的Method對象
       m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
       m3 = Class.forName("proxy.OrderInterface").getMethod("createOrder", new Class[] { Class.forName("proxy.OrderInfo") });
       m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
       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());
     }
   }
  // 創建訂單方法(代理方法)
  public final void createOrder(OrderInfo paramOrderInfo)
  {
    try
    {
      // 執行InvocationHandler實現類的invoke方法(方法參數在文章開頭有介紹)。
      this.h.invoke(this, m3, new Object[] { paramOrderInfo });
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final boolean equals(Object paramObject)
  {
    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()
  {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  //hashCode()   略
 }

代碼地址:https://gitee.com/chenxu_jdk/proxy-test

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 轉自https://blog.csdn.net/briblue/article/details/73928350前...
    扎Zn了老Fe閱讀 317評論 1 0
  • Java動態代理 引言 最近在看AOP代碼,其中利用到了Java動態代理機制來實現AOP織入。所以好好地把Java...
    草捏子閱讀 1,547評論 0 18
  • 前言 本文是我在學習代理模式時的一篇筆記,除了對代理模式、靜態和動態代理的概念和實現進行了描述外,還有關于動態代理...
  • Apline Linux是一個面向安全應用的輕量級Linux發行版。它采用了musl libc和busybox以減...
    猴子精h閱讀 3,579評論 0 2
  • 最近聽了一些對面宿舍好友和她室友鬧矛盾的事情,呼~~人和人真的好難友好相處呀! 剛剛從一個宿舍串寢回來,準確應該說...
    明眸盼兮巧笑嫣兮閱讀 303評論 4 1