【手写系列】纯手写实现JDK动态代理
前言
在Java領域,動態代理應用非常廣泛,特別是流行的Spring/MyBatis等框架。JDK本身是有實現動態代理技術的,不過要求被代理的類必須實現接口,不過cglib對這一不足進行了有效補充。本篇博客將涉及2個話題:第一,JDK動態代理的實現原理,帶你探索動態代理的實質面目;第二,自己動手寫代碼去實現JDK動態代理,去創造世界!
?
JDK動態代理
先寫一個例子,感性認識下動態代理~
業務接口:
interface?
業務實現類:
interface impl?
業務處理類:
Handler?
測試類:
test?
運行結果:
result?
在JDK動態代理中涉及如下角色:
業務接口Interface、業務實現類target、業務處理類Handler、JVM在內存中生成的動態代理類$Proxy0
動態代理原理圖:
動態代理的真實面目?
說白了,動態代理的過程是這樣的:
第一:Proxy通過傳遞給它的參數(interfaces/invocationHandler)生成代理類$Proxy0;
第二:Proxy通過傳遞給它的參數(ClassLoader)來加載生成的代理類$Proxy0的字節碼文件;
我們來看看上面例子中生成的$Proxy0的模樣:
$Proxy0?
首先,$Proxy是實現了我們的業務接口(Man)的,所以客戶端顯然可以調用業務接口的方法。
其次,注意到$Proxy是繼承自Proxy,并通過構造方法將業務處理類傳入給父類Proxy進行初始化。(實質上,你可以看看源碼,在Proxy中存在protected InvocationHandler h;)
初始化Proxy?
findObject?
很明顯,我們看到了業務接口的方法是如何被調用的:
最終都是回調業務處理類(具體的Handler)的invoke方法完成調用!
?
手寫代碼實現JDK動態代理
在上面,我們已經分析了JDK動態代理的整個調用過程,接下來,我們就來手寫實現它吧!
先來看一眼圖:
手寫實現JDK動態代理?
自定義InvocationHandler:
MyInvocationHandler?
實現MyInvocationHandler的業務處理Handler:
MyHandler?
自定義類加載器MyClassLoader:
MyClassLoader?
為什么要定義一個自定義的類加載器呢?它的作用是什么呢?
要知道,我們是想手寫JDK動態代理,那么我們將自己在內存中生成動態代理類,那么我們如何加載呢?這時候,就可以利用自定義的類加載器做到!
上述代碼,重寫了findClass方法,就是為了在指定路徑下加載指定的字節碼文件。
自定義MyProxy:
MyProxy?
MyProxy的作用就相當于JDK的Proxy。MyProxy做了哪些事情呢?
第一:需要根據interfaces接口構造出動態代理類需要的方法。(其實就是利用反射獲取)
第二:把動態生成的代理類(即.java文件)進行編譯,生成字節碼文件(即.class文件),然后利用類加載進行加載
第三:動態代理類進行加載后,利用反射機制,通過構造方法進行實例化,并在實例化時,初始化業務Hanlder
看一下MyProxy的其他方法:
編譯方法?
getMethodString方法?
運行結果?
我們來看一眼生成的$MyProxy0:
$MyProxy0?
OK,到這里,整個JDK的動態代理的實現原理以及手寫實現就結束了,你學到了么?
?
?
手寫系列相關爆文
【手寫系列】寫出我的第一個框架:迷你版Spring MVC
【手寫系列】透徹理解Spring事務設計思想之手寫實現
【手寫系列】透徹理解MyBatis設計思想之手寫實現
【手寫系列】純手寫實現一個高可用的RPC
【手寫系列】理解數據庫連接池底層原理之手寫實現
【手寫系列】對HashMap的思考及手寫實現
【手寫系列】寫一個迷你版的Tomcat
?
作者:張豐哲
鏈接:https://www.jianshu.com/p/58759fef38b8
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。
總結
以上是生活随笔為你收集整理的【手写系列】纯手写实现JDK动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【手写系列】写出我的第一个框架:迷你版S
- 下一篇: 不是技术也能看懂搜索引擎