jdk动态代理invoke方法自动运行原因
invoke 方法介紹
想要知道 invoke方法為什么會自動調用我們先要來了解一下這個方法 public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args)首先 該方法來自于接口InvocationHandler ,該接口中僅有一個invoke方法 ,該方法中有三個參數 * @param proxy the proxy instance that the method was invoked 這是接口源碼注釋中對第一個參數proxy的解釋:方法被調用的代理實例 我們可以認為它就是一個代理實例但是代理又是什么呢?這時候可能有小伙伴蒙了。 代理實例其實是代理類本身的一個實例,下面是我自己寫的一個動態代理小案例這是一個接口,動態代理必須有一個接口的存在 public interface PorxyInte {public void test(); } 這是一個實現了接口的實現類,寫的有些簡便,主要看起來清晰 public class ProImp implements PorxyInte {@Overridepublic void test() {System.out.println("test");} }這是測試類 通過了Proxy.newProxyInstance方法(具體作用等下說)返回了一個代理實例
ProImp proImp = new ProImp();//創建了實例類對象PorxyInte porxyInte =(PorxyInte) Proxy.newProxyInstance(ProImp.class.getClassLoader(), ProImp.class.getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("..."+proxy.getClass().getName());//輸出proxy對象的字節碼文件名Method[] declaredMethods = this.getClass().getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println(declaredMethod.getName());}method.invoke(proImp,null);return null;}});System.out.println(porxyInte.getClass().getName());//輸出實現類的字節碼文件名porxyInte.test(); com.sun.proxy.$Proxy0 // 實現類的字節碼文件名 ...com.sun.proxy.$Proxy0// 參數proxy的字節碼文件名 在這邊我們發現我自己定義的實現類和參數proxy的字節碼文件名是一致的而根據前面對參數proxy的注釋定義,我們不難得出$Proxy0就是一個代理類那么為什么我調用了.newProxyInstance方法會生成一個代理對象呢?newProxyInstance方法介紹
這是package java.lang.reflect.proxy下的一個靜態方法
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)我們需要注意的是它的三個參數
首先先介紹一下
第一個參數ClassLoader loader:類的加載器,傳入我們自定義類的加載器
第二個參數Class<?>[] interfaces 注意很重要 這個參數是傳入一個接口數組
第三個參數 h:類型是InvocationHandler,傳入InvocationHandler接口的子類
在newProxyInstance方法中 所做的幾件事情
!!重頭戲來了
第一步:
Class<?> cl = getProxyClass0(loader, intfs);調用了getProxyClass0方法, 該方法 需要傳入兩個參數 一個是類加載器,一個是接口數組
在方法getProxyClass0 中 會創建出一個類$Proxy0 ,并且創建出這個內部類的引用返回
我通過生出的內部類文件,反編譯出源碼可以看下:
那么先回到我們之前的疑問?invoke方法為什么會自動運行?
我相信現在小伙伴們也能理解
總體流程: 我在測試類中通過返回的$proxy引用調用test方法
這時候會去調用$proxy方法中的test方法
public final void test(){try{super.h.invoke(this, m3, null);return;}catch (Error ) { }catch (Throwable throwable){throw new UndeclaredThrowableException(throwable);}}在test方法中
super代表父類Proxy,h代表父類中的變量,也就是我們傳進來的InvocationHandler接口實例
然后又調用了實例中的invoke方法,這個時候是不是就一目了然,這就是為什么我們調用test方法,而 InvocationHandler中的invoke方法會自動運行的原因,這是因為在代理類中的test方法內容重新定義了
需要注意的點:
第一點:
很多剛接觸代理的小萌新包括博主我 在剛開始的時候都一直代理類當做是我們的自定義實現類對象
代理類不是我們定義的類,而是Proxy創建的$proxy類
第二點:
invoke方法中的第一個參數Proxy,這邊注意Proxy在invoke方法被賦值為this,this是誰呢?
他就是調用test方法的對象也就是我們的代理實例
到此為止,為什么動態代理invoke方法會自動運行的原因了
以上所有理解:都是博主自己的理解,如果有錯誤的地方,還請大家能一一指出,謝謝!!
總結
以上是生活随笔為你收集整理的jdk动态代理invoke方法自动运行原因的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 公众号带货软文应该怎么写?
- 下一篇: 还在手动部署jar包?太low了,动态上