為什麼java動態代理中,最終都轉換為調用invok方法?

Uchiha-Itachi-


基本介紹

  • 代理對象,不需要實現接口,但是目標對象要實現接口,否則不能用動態代理。
  • 代理對象的生成,是利用JDK的API,動態的內存中構建代理對象
  • 動態代理也叫做: JDK代理、接口代理

JDK中生成代理對象的API

  • 代理類所在包: java.lang.reflect.Proxy
  • JDK實現代理只需要使用newProxyInstance方法,但是該方法需要接收三個參數,完整寫法為:
    • static Object newProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h)

動態代理應用舉例

用動態代理實現事務:

UserService:

UserServiceImpl:

UserServiceInvocationHandler:



測試類:


結果為:


下面分析,為什麼java動態代理中,最終都轉換為調用invok方法?


我們先查看上面生成的proxy對象,



下面我們看看生成的 $proxy0代碼:

很清楚,動態代理類實現了UserService接口,繼承了Proxy類。


接口方法:


invoke方法傳入3個參數,這個invoke方法也就是4.1.2中我們提到的InvocationHandler接口的 invoke方法,那理解3個參數的意義也就很簡單了。

參數1傳入的為this——即$Proxy0本身,所以是內存中的動態代理對象

參數2傳入的為m3——也就是proxy.test.UserService中名為saveUser的方法,即接口中的方法。

參數3傳入的為null——因為saveUser方法沒有參數,所以為空。


完整代碼如下


碼農的一天


有些年頭沒寫代碼了,記憶中大概還能想起一些線索,翻出老代碼看了一下,試著回答一下你的問題,大概的思路是這樣的。


Java 在寫動態代理的時候一般步驟是這樣, 一般來說這三個東西必須有:

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Proxy;

import java.lang.reflect.Method;

第一步, 我們要定義一個接口,比方就叫做 DInterface, 簡單些就兩個方法:

第二步我們要定義一個類來實現上面這個接口,這個類就是我們的真實對象,名字就叫RealObject類,簡單些:

第三步,我們就要定義動態代理類了,並且每一個動態代理類都必須要實現 InvocationHandler 這個接口,這是死理,不能例外,就是通過這個東西來關聯。


如果沒記錯這地方應該會輸出一個xxxProxy.$Proxy0的類,所有的線路往$Proxy0源代碼裡找。


寫個簡單的測試

這裡通過Proxy.newProxyInstance方法來創建我們的代理對象,


大約的過程是這樣:

運行一下程序會發現它生成一個叫做$proxy0的類,它就是代理對象的真身。

查看這個$proxy0 源代碼就會發現它的構造器就直接調用了 super(invocationhandler),這裡invocationhandler在本例子就是 new DynamicProxyHandler(real),而它必須實現Invocationhandler接口,這個接口就一個方法invoke(), 所以動態代理自然然就轉換為調用invoke()方法了, 另外打開$

proxy0.class

看一下里面方法的參數傳遞就更清楚了。


有年頭沒做coding了,下班時看到頭條的邀請,憑記憶和粗看了下代碼回答,拋磚引玉,如有不周請高手繼續補充更多細節,一起分享,一起討論,共同學習。


珠鄉二哥


也不想回答太多,寫多了反而頭暈。動態代理底層就是java反射,動態生成了之後代理類,所以調用的反射裡的invoke


有理想有節操的鏟屎官


法()這裡通過反射獲得方法通過方法.invoke(對象);這樣來調用方法,懂了麼


分享到:


相關文章: