引入代理:
我們為什么要引入java的代理,除了當前類能夠提供的功能外,我們還需要補充一些其他功能。
最容易想到的情況就是權限過濾,我有一個類做某項業務,但是由於安全原因只有某些用戶才可以調用這個類,此時我們就可以做一個該類的代理類,要求所有請求必須通過該代理類,由該代理類做權限判斷,如果安全則調用實際類的業務開始處理。
可能有人說為什么我要多加個代理類?我只需要在原來類的方法里面加上權限過濾不就完了嗎?
在程序設計中有一個類的單一性原則問題,這個原則很簡單,就是每個類的功能盡可能單一。為什么要單一,因為只有功能單一這個類被改動的可能性才會最小。
如果你將權限判斷放在當前類里面,當前這個類就既要負責自己本身業務邏輯、又要負責權限判斷,那么就有兩個導致該類變化的原因,現在如果權限規則一旦變化,這個類就必需得改,顯然這不是一個好的設計。
(轉:https://www.cnblogs.com/silverLee/archive/2010/02/05/1664577.html)
用簡單的代碼來解釋代理的原理:
被代理類:
代理類:
測試:
注:代理一定要實現被代理類中的方法,於是我們經常會看見把代理和被代理中的方法抽象為一個借口,增加了一個約束。
java中是如何實現代理的:
這里就介紹管理基於接口的java代理 ,主要是用到了一個類和一個接口:
一個是 InvocationHandler(Interface)、另一個則是 Proxy(Class),這一個類和接口是實現我們動態代理所必須用到的
每一個動態代理類都必須實現InvocationHandler這個接口,這個接口中也只有唯一的一個具體實現方法invoke(),這個方法,當我們通過proxy類生成一個動態代理對象的時候,這個方法的調用就會被轉發為由InvocationHandler這個接口的 invoke 方法來進行調用
invoke方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
三個參數的具體意思:
proxy:生成的代理類對象
method:被代理類的某個具體方法
arg0:實現方法的具體參數
接口大概介紹完了,下面來介紹如何生成具體的代理類對象;
Proxy這個類的作用就是用來動態創建一個代理對象的類,它提供了許多的方法,但是我們用的最多的就是 newProxyInstance 這個方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
三個參數的具體意義:
loader:類加載器,一般使用被代理類的類加載器,當然使用接口的類加載器也是可以的
InvocationHandler:表示的是我將要給我需要代理的對象提供一組什么接口,如果我提供了一組接口給它,那么這個代理對象就宣稱實現了該接口(多態),這樣我就能調用這組接口中的方法了
h:就是我們上面所說的InvocationHandler接口具體實現對象.
介紹完這兩個重要類和接口就可以實現java的基於接口的代理了