標籤:oca err ext 實現 color min system style 靜態
代理顧名思義,就是一個中介層,當我們要使用某個方法時,不直接調用,而是告訴代理,讓代理替我們去要求方法,並返回結果。在這個過程中,我們只知道代理執行並返回給了我們操作結果,至於它有沒有其他動作並不知道,但這個也無關緊要,因為不管代理在請求實際方法之前和之後做了什麼,對我們都不會產生任何影響。由於代理的這個特性,可以用來進行記錄日誌等操作。
代理分為靜態代理和動態代理。
靜態代理
靜態代理需要我們在調用者和具體的執行者之間建立一個代理類,其實現需要被代理的介面並持有一個此介面,具體代碼如下:
介面類(被代理):
public interface Hello { void say(String name);}
代理類:
public class HelloProxy implements Hello {? private Hello helloImpl;? public HelloProxy() { this.helloImpl = new HelloImpl(); // HelloImpl為一個Hello介面的一個普通實作類別 }? @Override public void say(String name) { System.out.println("before say"); helloImpl.say(name); System.out.println("after say"); }}
使用的時候只需要new一個代理類賦值給介面即可:Hello hello = new HelloProxy(),之後的執行會由代理類去負責。但是這麼做有一個問題就是對每個需要代理的類,都需要建立一個對應的代理類,即使代理類的邏輯都是相似的,動態代理就是解決這個問題的。
動態代理
動態代理相當於在調用者和代理類之間又增加了一個中介層,在這個中介層中完成代理類的邏輯,達到複用代碼的效果。這個中介層需要實現InvocationHandler介面,並持有一個被代理的類,大致代碼如下:
public class Myproxy implements InvocationHandler {? private Object target; // 被代理的類? public Myproxy(Object target) { this.target = target; }? @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before invoke"); // 執行代理的方法前進行的操作 Object invoke = method.invoke(target, args); // 調用執行被代理的方法 System.out.println("after invoke"); // 執行代理的方法後進行的操作 return invoke; // 返回方法執行結果 }}
使用時,使用Proxy的靜態方法擷取代理類,將其強轉為對應的介面,之後可以同靜態代理類同樣使用。
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
其中loader為類載入器,interfaces為要代理的介面,h為之前定義的實現InvocationHandler介面的類的執行個體。
這個方法會返回一個代理類,其實現的要代理的介面,並持有一個實現InvocationHandler介面的執行個體,代理類的代碼大致如下:
public final class $Proxy0 extends Proxy implements Hello{? public $Proxy0(InvocationHandler paramInvocationHandler) { super(paramInvocationHandler); }? public final String say() { try { return ((String)this.h.invoke(this, m3, null)); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } }?}
如上代碼我們可以將其強轉為Hello介面,實際調用的時候會調用InvocationHandler實作類別中的invoke方法,而其中就是我們實現的代理業務,當然,也包括實際的業務。
這樣,對於有相同代理業務的類,我們只要實現InvocationHandler介面,在其中的invoke方法實現需要代理的業務,使用時只要使用Proxy.newProxyInstance靜態方法,傳入對應得參數即可得到需要的代理類,再將其強轉賦值給需要的介面,即可正常使用。
Java代理筆記