動態代理實例

做者:易哥
連接:https://zhuanlan.zhihu.com/p/...
來源:知乎
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。java

1 動態代理

動態代理的實現方式經常使用的有兩種:post

  • 反射實現:基於反射實現,目標對象必需要有接口。生成的代理類是接口的一個實現類
  • Cglib實現:基於字節碼實現,效率稍低,但目標對象不須要有接口。生成的代理類是目標類的子類,所以目標類不能是final的。

2 背景介紹
在Java中java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler接口,經過使用這個類和接口就能夠生成動態代理對象,只能針對接口作代理。
接口和目標類沒有任何變化,只不過爲了增長難度,咱們增長了返回值。
接口以下,除了增長了方法的返回值外無任何變化: spa

目標類以下,無任何變化: 3d

2 反射調用方法

接下來,咱們使用JDK完成動態代理,對於代理類只須要實現InvocationHandler接口便可,而且要實現其中的invoke()方法。
invoke()中須要傳入目標對象、目標對象的方法、調用目標所需的參數,傳入後,就會直接調用指定對象的指定方法了。 代理

咱們使用舉例: code

咱們只要建立一個ProxyHandler對象,直接調用invoke方法,傳入其中所須要的對象、方法、參數,即可以執行咱們寫好的invoke方法,而且invoke中還能夠調用指定對象的指定方法。這種方法很是靈活,ProxyHandler創建後,調用invoke方法時,能夠傳入任何對象、任何方法,很是自由。
這種操做只是經過反射調用的指定對象的指定方法,並無使用代理。可是能夠用它來實現動態代理。咱們只要生成一個代理對象,接口全部的操做都由代理對象來完成。其中,代理對象中再經過這種反射的方式去調用目標對象便可了。對象

3 動態代理

在使用動態代理時,ProxyHandler須要稍加改造,即在構造方法中傳入目標對象。可是這裏要注意的是,與靜態代理不一樣,這裏的目標對象的類型是任意的,所以同一個ProxyHandler能夠用來代理不一樣的目標對象。 blog

在使用時,以下: 接口

首先,咱們定義了被代理的類的實例,而且傳給了proxyHandler。而後,咱們咱們直接調用了Proxy的靜態方法newProxyInstance生成了一個接口的實例,這個實例就是代理(並且它知道它代理的是user對象,初始化時已經傳給它了)。
而後,直接對這個實例調用方法就能夠了,對這個接口調用方法,就至關於執行了invoke中的操做,輸出以下:rem

pre words
hello Lily
post words

注意,在這種實現中,目標類target是在初始化時寫死,而且在invoke時直接調用的,若是在invoke中直接調用傳來的proxy對象,則會引起循環調用,形成死循環。
咱們查看下Proxy類中的靜態方法,newProxyInstance方法:

該方法用來返回指定接口的一個代理類實例。
輸入參數有:

  • 生成代理類實例的classLoader;
  • 要知足的接口;
  • 代理類的處理器,即具體的實現。

這樣就指明瞭用哪一個處理器處理哪一個接口中的操做,以及該對象如何生成出來。 生成的對象就是一個代理對象,就能夠代理接口的操做了。

相關文章
相關標籤/搜索