回覆列表
-
1 # 珠鄉二哥
-
2 # 一江一城一巷
也不想回答太多,寫多了反而頭暈。動態代理底層就是java反射,動態生成了之後代理類,所以呼叫的反射裡的invoke
-
3 # 程式猿W
基本介紹代理物件,不需要實現介面,但是目標物件要實現介面,否則不能用動態代理。代理物件的生成,是利用JDK的API,動態的記憶體中構建代理物件動態代理也叫做: JDK代理、介面代理JDK中生成代理物件的API代理類所在包: java.lang.reflect.ProxyJDK實現代理只需要使用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
看一下里面方法的引數傳遞就更清楚了。