成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

這一次徹底搞懂JDK動態代理

開發 前端
靜態代理這個模式本身有個大問題,若類方法數量越來越多的時候,代理類的代碼量十分龐大的。所以引入動態代理.

[[409031]]

動態代理 V.S 靜態代理

Proxy類的代碼被固定下來,不會因為業務的逐漸龐大而龐大

可以實現AOP編程,這是靜態代理無法實現的

解耦,如果用在web業務下,可以實現數據層和業務層的分離

動態代理的優勢就是實現無侵入式的代碼擴展。

靜態代理這個模式本身有個大問題,若類方法數量越來越多的時候,代理類的代碼量十分龐大的。所以引入動態代理

動態代理

Java中動態代理的實現的關鍵:

  • Proxy
  • InvocationHandler

InvocationHandler#invoke

  • method 調用的方法,即需要執行的方法
  • args 方法的參數
  • proxy 代理類的實例 圖片

JDK動態代理

JDK動態代理模式里有個攔截器,在JDK中,只要實現了InvocationHandler接口的類就是一個攔截器類。攔截器的作用:控制目標對象的目標方法的執行。

攔截器的具體操作步驟:

1.引入類

目標類和一些擴展方法相關的類

2.賦值

調用構造器,給相關對象賦值

3.合并邏輯處理

在invoke方法中把所有的邏輯結合在一起。最終決定目標方法是否被調用

示例

思考如下問題:

代理對象由誰產生

JVM,不像靜態代理,我們得自己new個代理對象。

代理對象實現了什么接口

實現的接口是目標對象實現的接口。同靜態代理中代理對象實現的接口。那個繼承關系圖還是相同的。代理對象和目標對象都實現一個共同的接口。就是這個接口。所以Proxy.newProxyInstance()方法返回的類型就是這個接口類型。

代理對象的方法體是什么

代理對象的方法體中的內容就是攔截器中invoke方法中的內容。

所有代理對象的處理邏輯,控制是否執行目標對象的目標方法。都是在這個方法里面處理的。

攔截器中的invoke方法中的method參數是在什么時候賦值的

在客戶端,代理對象調用目標方法的時候,此實例中為:

  1. proxyObj.business(); 

實際上進入的是攔截器中的invoke方法,這時攔截器中的invoke方法中的method參數會被賦值。

為啥這叫JDK動態代理

因為該動態代理對象是用JDK相關代碼生成。

很多同學對動態代理一直很迷糊,在于理解錯了

  1. proxyObj.business(); 
  2. $Proxy0 

沒有發現這個 proxyObj 和 Proxy 類之間的聯系,一直好奇

最后調用的business()是怎么和 invoke() 聯系上的?

invoke又怎么知道business的存在?

因為大多同學不知道 $Proxy0 類,看看下面的 $Proxy0 源碼,相信你完全可以理解動態代理了。

我們雖然沒有顯式調用invoke,但該方法確實被執行了。

可以從newProxyInstance方法作為突破口,我們先來看一下Proxy類中newProxyInstance方法的源代碼:

  1. public static Object newProxyInstance(ClassLoader loader, 
  2.                                       Class<?>[] interfaces, 
  3.                                       InvocationHandler h) { 
  4.     final Class<?>[] intfs = interfaces.clone(); 
  5.     final SecurityManager sm = System.getSecurityManager(); 
  6.     if (sm != null) { 
  7.         checkProxyAccess(Reflection.getCallerClass(), loader, intfs); 
  8.     } 
  9.  
  10.     /* 
  11.      * 查找或生成指定的代理類 
  12.      * 創建代理類$Proxy0 
  13.      * $Proxy0類實現了interfaces的接口,并繼承了Proxy類 
  14.      */ 
  15.     Class<?> cl = getProxyClass0(loader, intfs); 
  16.  
  17.     /* 
  18.      * 使用指定的調用處理程序調用其構造器 
  19.      */ 
  20.     try { 
  21.         if (sm != null) { 
  22.             checkNewProxyPermission(Reflection.getCallerClass(), cl); 
  23.         } 
  24.         // 形參為InvocationHandler類型的構造器 
  25.         final Constructor<?> cons = cl.getConstructor(constructorParams); 
  26.         final InvocationHandler ih = h; 
  27.         if (!Modifier.isPublic(cl.getModifiers())) { 
  28.             AccessController.doPrivileged(new PrivilegedAction<Void>() { 
  29.                 public Void run() { 
  30.                     cons.setAccessible(true); 
  31.                     return null
  32.                 } 
  33.             }); 
  34.         } 
  35.         return cons.newInstance(new Object[]{h}); 
  36.     } ... 

Proxy.newProxyInstance 做了什么呢?

  • 根據參數loader和interfaces調用方法 getProxyClass(loader, interfaces)創建代理$Proxy0類。$Proxy0類 實現了interfaces的接口,并繼承了Proxy類
  • 實例化$Proxy0,并在構造器把DynamicSubject傳過去,接著$Proxy00調用父類Proxy的構造器,為h賦值

$Proxy0的源碼:

  1. package com.sun.proxy; 
  2.  
  3. public final class $Proxy0 extends Proxy implements TargetInterface { 
  4.     private static Method m1; 
  5.     private static Method m3; 
  6.     private static Method m2; 
  7.     private static Method m0; 
  8.  
  9.     public $Proxy0(InvocationHandler var1) throws  { 
  10.         super(var1); 
  11.     } 
  12.  
  13.     public final boolean equals(Object var1) throws  { 
  14.         try { 
  15.             return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); 
  16.         }... 
  17.     } 
  18.  
  19.     public final void business() throws  { 
  20.         try { 
  21.             super.h.invoke(this, m3, (Object[])null); 
  22.         }... 
  23.     } 
  24.  
  25.     public final String toString() throws  { 
  26.         try { 
  27.             return (String)super.h.invoke(this, m2, (Object[])null); 
  28.         }... 
  29.     } 
  30.  
  31.     public final int hashCode() throws  { 
  32.         try { 
  33.             return (Integer)super.h.invoke(this, m0, (Object[])null); 
  34.         }... 
  35.     } 
  36.  
  37.     static { 
  38.         try { 
  39.             m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); 
  40.             m3 = Class.forName("com.javaedge.design.pattern.structural.proxy.dynamicproxy.jdkdynamicproxy.TargetInterface").getMethod("business"); 
  41.             m2 = Class.forName("java.lang.Object").getMethod("toString"); 
  42.             m0 = Class.forName("java.lang.Object").getMethod("hashCode"); 
  43.         }... 
  44.     } 

接著把得到的$Proxy0實例強轉成TargetInterface,并將引用賦給TargetInterface。當執行proxyObj.business(),就調用了$Proxy0類中的business()方法,進而調用父類Proxy中的h的invoke()方法。即InvocationHandler.invoke()。

最后提醒Proxy#getProxyClass返回的是Proxy的Class類,而非很同學想當然認為的“被代理類的Class類”! 

本文轉載自微信公眾號「JavaEdge」,可以通過以下二維碼關注。轉載本文請聯系JavaEdge公眾號。

 

責任編輯:武曉燕 來源: JavaEdge
相關推薦

2021-08-29 08:14:30

GPU CSS gpu

2024-05-15 10:14:00

CRDT數據類型協同編輯

2019-11-08 16:05:54

Promise前端鏈式調用

2019-09-12 09:40:34

秒殺系統高并發

2024-03-11 08:47:30

CRDT數據類型協同編輯

2018-08-07 14:45:52

編程語言JavaScripthtml

2021-03-11 12:15:37

Kubernetes云原生容器

2021-04-28 09:55:52

JavaLock接口并發編程

2020-08-13 07:04:45

跨域CORS瀏覽器

2019-06-05 13:00:00

2024-05-20 00:00:00

代碼主線程

2016-03-31 17:01:26

桂林甲天下

2018-07-23 16:13:27

Google歐盟Android

2025-04-09 10:36:32

2024-10-09 12:05:27

2014-07-18 17:14:16

小米蘋果雷軍

2016-01-06 11:15:03

VR

2019-04-12 11:25:24

華為

2016-11-08 07:58:02

樂視難關科技新聞早報

2019-11-05 11:17:11

Java虛擬機技術Java 堆
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品一级 | 精品1区2区 | 婷婷激情综合 | 中文字幕av网站 | 亚洲一区二区三区视频 | 羞羞网站免费观看 | 狠狠久久综合 | 久久一视频 | 成人做爰69片免费观看 | 精品国产乱码一区二区三区a | 五月天天色 | 欧洲精品码一区二区三区免费看 | www.99热.com| 国产特一级黄色片 | 国产欧美日韩在线一区 | www,黄色,com | 国精日本亚洲欧州国产中文久久 | 日韩中文字幕在线播放 | 天天干天天爱天天爽 | 亚洲视频一区在线观看 | 亚洲精品永久免费 | 久久国产精品免费一区二区三区 | 国产激情视频在线观看 | 亚洲精品一区中文字幕乱码 | 中文字幕av一区 | 中文字幕亚洲视频 | 日韩图区 | 97人人澡人人爽91综合色 | 日韩一区二区在线视频 | 亚洲综合精品 | 人人干人人看 | 国产视频不卡一区 | 国产精品3区 | 日韩在线国产精品 | 99国产精品久久久久老师 | 一区在线播放 | 久久99久久 | 永久免费av | 国产午夜精品福利 | 黄网站在线观看 | 国产区在线看 |