JAVA動態代理

JAVA動態代理

借鑑:java

https://www.zhihu.com/question/20794107/answer/658139129?utm_source=wechat_session&utm_medium=social&utm_oi=911918804941021184&utm_content=sec數組

https://blog.csdn.net/yangaiyu/article/details/73827043session

  • 若本身實現代碼加強,則須要爲每一個目標對象單獨編寫一個代理Class對象而後用類加載器加載,實例化,再調用,這樣每一個目標對象都得單獨地編寫代理Class對象以達到目的(即靜態代理)。數據結構

  • 爲了減小代理類地編寫,咱們類的消息通常都由Class對象在JVM方法區中被加載(反射和new都是),若想不編寫代理class還要有目標類的信息,天然而然地能夠想到接口,若能對接口進行動態代理,則可將實現該接口並調用該接口中的方法(可能不止實現一個接口)的目標類歸爲以類進行代碼編寫(這就是爲何要使用動態代理的緣由),可是,接口並不能實例化jvm

  • 但java.lang.reflect.Proxy類有個getProxyLoader(ClassLoader,interfaces)方法,只要你給他傳入類加載器和一組接口,它就能給你返回代理Class對象。(意味着它變成了一個對象,能夠帶有構造器進行實例化)函數

  • 有了代理Class對象(代理Class對象爲代理類->數據結構,代理對象爲實例化的對象),咱們能夠經過該對象獲得有參的構造器(基於InvocationHandle接口),咱們就能夠反射建立實例了,而基於上述接口的構造器能夠基於實例化的InvocationHandle接口的對象實例化,使得代理對象經過handler對象中的invoke方法去加強目標對象(InvocationHandle接口是一個規範,代理對象中會有成員變量去接收它,併爲他的proxy、method、args等傳參,爲了便於設計把他提取出來
InvocationHandler handler = new DynamicProxy(realSubject);
Object invoke(Object proxy, Method method, Object[] args) throws Throwable

proxy:  指代咱們所代理的那個真實對象
method:  指代的是咱們所要調用真實對象的某個方法的Method對象
args:  指代的是調用真實對象某個方法時接受的參數

可能會覺得返回的這個代理對象會是Calculator類型的對象,或者是InvocationHandler的對象,結果卻不是,首先咱們解釋一下爲何咱們這裏能夠將其轉化爲Subject類型的對象?緣由就是在getPorxyClass這個方法的第二個參數上,咱們給這個代理對象提供了一組什麼接口,那麼我這個代理對象就會實現了這組接口,這個時候咱們固然能夠將這個代理對象強制類型轉化爲這組接口中的任意一個,由於這裏的接口是Subject類型,因此就能夠將其轉化爲Subject類型了。.net

同時咱們必定要記住,以上獲取代理Class、獲得有參構造函數、實例化後建立的代理對象是在jvm運行時動態生成的一個對象,它並非咱們的InvocationHandler類型,也不是咱們定義的那組接口的類型,而是在運行是動態生成的一個對象,而且命名方式都是這樣的形式,以$開頭,proxy爲中,最後一個數字表示對象的標號。設計

  • 上面的並無傳入目標對象,須要在invoke裏新建相應的對象,咱們經常使用的是傳入相應的目標對象,而將上面的封裝爲一個函數,以適用於更多的對象調用,而更經常使用的是Proxy.newProxyInstance()方法,直接將上述流程都封裝了。
* public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

loader:一個ClassLoader對象,定義了由哪一個ClassLoader對象來對生成的代理對象進行加載

interfaces:一個Interface對象的數組,表示的是我將要給我須要代理的對象提供一組什麼接口,若是我提供了一組接口給它,那麼這個代理對象就宣稱實現了該接口(多態),這樣我就能調用這組接口中的方法了

h:一個InvocationHandler對象,表示的是當我這個動態代理對象在調用方法的時候,會關聯到哪個InvocationHandler對象上

  • 以後在invoke中調用method.invoke時,即爲代理對象調用真實對象的方法時,其會自動的跳轉到代理對象關聯的handler對象的invoke方法來進行調用(反射實現),能夠深刻getPorxyClass與創造構造器的三個步驟或newProxyInstance中查看相關實現。
  • 以上即是動態代理的所有流程了

相關文章
相關標籤/搜索