日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

詳解Java的Proxy動態代理機制

瀏覽:28日期:2022-08-09 16:36:33
目錄一、Jvm加載對象二、代理模式2.1、基本描述2.2、靜動態模式三、靜態代理四、動態代理4.1、場景描述4.2、基礎API案例4.3、代理類結構4.4、JDK源碼五、源代碼地址一、Jvm加載對象

在說Java動態代理之前,還是要說一下Jvm加載對象的過程,這個依舊是理解動態代理的基礎性原理:

詳解Java的Proxy動態代理機制

Java類即源代碼程序.java類型文件,經過編譯器編譯之后就被轉換成字節代碼.class類型文件,類加載器負責讀取字節代碼,并轉換成java.lang.Class對象,描述類在元數據空間的數據結構,類被實例化時,堆中存儲實例化的對象信息,并且通過對象類型數據的指針找到類。

過程描述:源碼->.java文件->.class文件->Class對象->實例對象

所以通過New創建對象,獨斷其背后很多實現細節,理解上述過程之后,再了解一個常用的設計模式,即代理模式。

二、代理模式2.1、基本描述

代理模式給某一個(目標)對象提供一個代理對象,并由代理對象持有目標對象的引用。所謂代理,就是一個對象代表另一個對象執行相應的動作程序。而代理對象可以在客戶端和目標對象之間起到中介的作用。

詳解Java的Proxy動態代理機制

代理模式在實際的生活中場景很多,例如中介、律師、代購等行業,都是簡單的代理邏輯,在這個模式下存在兩個關鍵角色:

目標對象角色:即代理對象所代表的對象。

代理對象角色:內部含有目標對象的引用,可以操作目標對象;AOP編程就是基于這個思想。

2.2、靜動態模式 靜態代理:在程序運行之前確定代理角色,并且明確代理類和目標類的關系。 動態代理:基于Java反射機制,在JVM運行時動態創建和生成代理對象。三、靜態代理

基于上述靜態代理的概念,用一段代碼進行描述實現,基本邏輯如下:

明確目標對象即被代理的對象; 定義代理對象,通過構造器持有目標對象; 代理對象中定義前后置增強方法;

目標對象與前后置增強代碼就組成了代理對象,這樣就不用直接訪問目標對象,像極了電視劇中那句話:我是律師,我的當事人不方便和你對話。

public class Proxy01 { public static void main(String[] args) {TargetObj targetObj = new TargetObj() ;ProxyObj proxyObj = new ProxyObj(targetObj) ;proxyObj.invoke(); }}class TargetObj { public void execute (){System.out.println('目標類方法執行...'); }}class ProxyObj { private TargetObj targetObj ; /** * 持有目標對象 */ public ProxyObj (TargetObj targetObj){this.targetObj = targetObj ; } /** * 目標對象方法調用 */ public void invoke (){before () ;targetObj.execute();after () ; } /** * 前后置處理 */ public void before (){System.out.println('代理對象前置處理...'); } public void after (){System.out.println('代理對象后置處理...'); }}

靜態代理明確定義了代理對象,即有一個代理對象的.java文件加載到JVM的過程,很顯然的一個問題,在實際的開發過程中,不可能為每個目標對象都定義一個代理類,同樣也不能讓一個代理對象去代理多個目標對象,這兩種方式的維護成本都極高。

代理模式的本質是在目標對象的方法前后置入增強操作,但是又不想修改目標類,通過前面反射機制可以知道,在運行的時候可以獲取對象的結構信息,基于Class信息去動態創建代理對象,這就是動態代理機制。

順便說一句:技術的底層實現邏輯不好理解是眾所周知,然而基礎知識點并不復雜,例如代理模式的基本原理,但是結合到實際的復雜應用中(AOP模式),很難活靈活現的理解到是基于反射和動態代理的方式實現的。

四、動態代理4.1、場景描述

基于一個場景來描述動態代理和靜態代理的區別,即最近幾年很火的概念,海外代購:

詳解Java的Proxy動態代理機制

在代購剛興起的初期,是一些常去海外出差的人,會接代購需求,即代理人固定;后來就興起海外代購平臺,海淘等一系列產品,即用戶代購需求(目標對象)由代購平臺去實現,但是具體誰來操作這個就看即時分配,這個場景與動態代理的原理類似。

4.2、基礎API案例

首先看兩個核心類,這里簡述下概念,看完基本過程再細聊:

Proxy-創建代理對象,核心參數:

ClassLoader:(目標類)加載器; Interfaces:(目標類)接口數組; InvocationHandler:代理調用機制;

InvocationHandler-代理類調用機制:

invoke:這個上篇說的反射原理; method:反射類庫中的核心API;

目標對象和接口

interface IUser { Integer update (String name) ;}class UserService implements IUser { @Override public Integer update(String name) {Integer userId = 99 ;System.out.println('UserId='+userId+';updateName='+name);return userId ; }}

代理對象執行機制

class UserHandler implements InvocationHandler { private Object target ; public UserHandler (Object target){this.target = target ; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println('before()...');Object result = method.invoke(target, args);System.out.println('after()...');return result; }}

具體組合方式

public class Proxy02 { public static void main(String[] args) {/* * 生成$Proxy0的class文件 */System.getProperties().put('sun.misc.ProxyGenerator.saveGeneratedFiles', 'true');/* * 目標對象信息 */IUser userService = new UserService();ClassLoader classLoader = userService.getClass().getClassLoader();Class<?>[] interfaces = UserService.class.getInterfaces() ;/* * 創建代理對象 */InvocationHandler userHandler = new UserHandler(userService);/* * 代理類對象名 * proxyClassName=com.java.proxy.$Proxy0 */String proxyClassName = Proxy.newProxyInstance(classLoader,interfaces,userHandler).getClass().getName();System.out.println('proxyClassName='+proxyClassName);/* * 具體業務實現模擬 */IUser proxyUser1 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);IUser proxyUser2 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);proxyUser1.update('cicada') ;proxyUser2.update('smile') ; }}

這里之所以要生成代理類的結構信息,因為從JVM加載的過程看不到相關內容,關鍵信息再次被獨斷:

javap -v Proxy02.class

詳解Java的Proxy動態代理機制

查看代理類名稱

/* * proxyClassName=com.java.proxy.$Proxy0 */String proxyClassName = Proxy.newProxyInstance(classLoader,interfaces,userHandler).getClass().getName();System.out.println('proxyClassName='+proxyClassName);

下意識輸出代理對象名稱,這里即對應JVM機制,找到Class對象名,然后分析結構,這樣就明白動態代理具體的執行原理了。

生成代理類.class文件

System.getProperties().put('sun.misc.ProxyGenerator.saveGeneratedFiles', 'true');

通過上面JVM加載對象的機制可知,描述代理類的Class對象一定存在,只是在運行時并沒有生成顯式的.class文件,通過上面生成代理類.class的語法,會在項目目錄的/com/java/proxy路徑下創建文件。

順便說一句:作為一只程序員,復雜總是和我們環環相繞,說好的簡單點呢?

4.3、代理類結構

繼承與實現

class $Proxy0 extends Proxy implements IUser {}

從代理類的功能來思考,可以想到需要繼承Proxy與實現IUser接口,還有就是持有調用機制的具體實現類,用來做業務增強。

構造方法

public $Proxy0(InvocationHandler var1) throws { super(var1);}

通過構造方法,持有UserHandler具體的執行機制對象。

接口實現

final class $Proxy0 extends Proxy implements IUser { private static Method m3; public final Integer update(String var1) throws {try { return (Integer)super.h.invoke(this, m3, new Object[]{var1});} catch (RuntimeException | Error var3) { throw var3;} catch (Throwable var4) { throw new UndeclaredThrowableException(var4);} }}

目標類的基本需求update()方法,通過代理類進行承接,并基于UserHandler實現具體的增強業務處理。

基礎方法

final class $Proxy0 extends Proxy implements IUser { private static Method m0; private static Method m1; private static Method m2; public $Proxy0(InvocationHandler var1) throws {super(var1); } static {try { m1 = Class.forName('java.lang.Object').getMethod('equals', Class.forName('java.lang.Object')); m2 = Class.forName('java.lang.Object').getMethod('toString'); m3 = Class.forName('com.java.proxy.IUser').getMethod('update', Class.forName('java.lang.String')); m0 = Class.forName('java.lang.Object').getMethod('hashCode');} catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage());} } 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 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);} }}

基于Object類,定義Java中幾個常用方法equals()判斷,toString()方法,hashCode()值,這個在分析Map源碼的時候有說過為什么這幾個方法通常都是一起出現。

4.4、JDK源碼

上面是案例執行的過程和原理,還有一個關鍵點要明白,即JDK源碼的邏輯:

IUser proxyUser = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);

Proxy提供的靜態方法newProxyInstance(),通過各個參數的傳入,構建一個新的代理Class對象,即$Proxy0類的結構信息,這里再回首看下三個核心參數:

ClassLoader:基于JVM運行過程,所以需要獲取目標類UserService的類加載器; Interfaces:目標類UserService實現的接口,從面向對象來考慮,接口與實現分離,代理類通過實現IUser接口,模擬目標類的需求; InvocationHandler:代理類提供的功能封裝即UserHandler,可以在目標方法調用前后做增強處理;

最后總結一下動態代理的實現的核心技術點:Jvm加載原理、反射機制、面向對象思想;每次閱讀JDK的源碼都會驚嘆設計者的鬼斧神工,滴水穿石堅持才會有收獲。

五、源代碼地址

GitHub·地址

https://github.com/cicadasmile/java-base-parent

GitEE·地址

https://gitee.com/cicadasmile/java-base-parent

以上就是詳解Java的Proxy動態代理機制的詳細內容,更多關于Java Proxy 動態代理機制的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日韩精品免费一区二区在线观看 | 欧美专区在线| 欧美精品一区二区久久| 婷婷亚洲综合| 偷拍精品精品一区二区三区| 人人草在线视频| 五月激情久久| 在线一区电影| 伊人久久一区| 日韩精品中文字幕吗一区二区| 亚洲a成人v| 久久国际精品| 国产一区调教| 中文字幕一区久| 欧美肉体xxxx裸体137大胆| 91久久久精品国产| 蜜桃av一区| 国产日韩欧美一区二区三区 | 国产精品视频3p| 国产在线不卡一区二区三区| 桃色一区二区| 中文欧美日韩| 日韩1区2区3区| 麻豆国产欧美一区二区三区| 青青青免费在线视频| 欧美日韩四区| 色综合视频一区二区三区日韩| 国产精品一线| 99tv成人| 亚洲青青久久| 国产欧美69| 成人午夜精品| 午夜精品福利影院| 精品久久久久久久| 欧美日韩国产高清| 亚洲免费成人av在线| 精品一区二区三区免费看| 99精品国产一区二区三区| 免费成人在线视频观看| 免费在线欧美黄色| 今天的高清视频免费播放成人| 亚洲精品人人| 98精品久久久久久久| 日韩中文字幕一区二区三区| 久久爱www成人| 欧美一区二区三区高清视频 | 久久精品九色| 午夜在线一区二区| 麻豆久久久久久| 久久精品国产大片免费观看| 日韩在线麻豆| 日韩电影免费网站| 日韩av中文字幕一区二区三区| 另类专区亚洲| 无码日韩精品一区二区免费| 成人国产精品| 日韩制服丝袜av| 麻豆一区二区三| 99综合视频| 国产一区二区三区91| 视频一区视频二区中文| 日韩成人精品一区二区| 亚洲男人在线| 久久精品不卡| 久久免费影院| 一区二区三区网站| 美女网站视频一区| 国产欧美69| 麻豆精品网站| 久久久男人天堂| 欧美亚洲一区二区三区| 欧美成人综合| 欧美激情精品| 蜜桃视频在线观看一区二区| 日韩国产一区二区| 国产乱人伦精品一区| 中国女人久久久| 高清av不卡| 国产伦精品一区二区三区在线播放 | 国产欧美一级| 久久xxxx精品视频| 久久久久久久久久久9不雅视频| 国产精品亚洲综合在线观看| 老司机久久99久久精品播放免费| se01亚洲视频| 国产精品网址| 日韩久久一区| 一本综合精品| 黄色精品网站| 久久精品123| 精品一二三区| 国产欧美日韩免费观看| 亚洲最新av| aa亚洲婷婷| 99精品电影| 日韩高清欧美| 97人人精品| 国产成人免费av一区二区午夜| 青青伊人久久| 日韩高清一级| 亚洲人成网77777色在线播放| 亚洲手机在线| 亚洲一级高清| 欧美精品羞羞答答| 亚洲网站视频| 99精品在线观看| 日本免费一区二区三区四区| 国产一区二区精品久| 韩国女主播一区二区三区| 你懂的亚洲视频| 欧美黄页在线免费观看| 日韩成人午夜精品| 日韩精品一区二区三区中文| 91久久黄色| 国产一区二区高清| 国产午夜精品一区二区三区欧美 | 久久久天天操| 日韩在线综合| 麻豆mv在线观看| 亚洲综合电影| 成人美女视频| 99精品网站| 精品一区免费| 亚洲国产综合在线看不卡| 精品免费av在线| 日韩精品一卡| 99成人在线视频| 女人天堂亚洲aⅴ在线观看| 欧美国产91| 国产视频一区欧美| 亚洲精品乱码| 日韩国产欧美视频| 国产精品天天看天天狠| 精品国产日韩欧美精品国产欧美日韩一区二区三区| 国产精品毛片久久久| 麻豆精品少妇| 国产粉嫩在线观看| 久久精品国产大片免费观看| 亚洲国产专区校园欧美| 99久久久国产精品美女| 欧美a级一区| 亚洲网址在线观看| 国产日本精品| 久久精品三级| 999久久久免费精品国产| 精品一区亚洲| 亚洲精品日本| 老牛国内精品亚洲成av人片| 亚洲黄色免费av| 欧美 日韩 国产一区二区在线视频| 伊人精品视频| 日韩精品午夜视频| 国产精品天天看天天狠| 国产白浆在线免费观看| 欧美日韩在线播放视频| 首页欧美精品中文字幕| 久久国产麻豆精品| 高清一区二区| 宅男噜噜噜66国产日韩在线观看| 亚州国产精品| 牛牛精品成人免费视频| 色婷婷精品视频| 久久国产精品久久w女人spa| 久久国内精品自在自线400部| 91一区二区| 国产视频一区三区| 国产欧美欧美| 久久久精品午夜少妇| 综合五月婷婷| 久久精品一区二区国产| 久久中文字幕av| 日韩精品亚洲专区| av资源亚洲| 综合亚洲自拍| 精品99在线| 丝袜国产日韩另类美女| 久久中文欧美| 亚洲自拍另类| 国产成人精品一区二区三区视频| 亚洲一本视频| 国产剧情一区| 激情婷婷综合| 国产高清视频一区二区| 午夜国产精品视频| 欧美日韩伊人| 欧美a级片一区| 欧美激情在线精品一区二区三区| 免费av一区| 欧美激情日韩| 免费在线观看成人| 国内在线观看一区二区三区| 美女网站久久| 国产在线看片免费视频在线观看| 中文字幕一区二区av| 黄色在线网站噜噜噜| 中文字幕一区二区av| 成人精品亚洲| 国产欧美一区二区精品久久久| 影音先锋久久| 国产一区二区精品福利地址|