# 代理模式 目標類和代理類,不是直接調用目標類對象,而是通過調用代理類的對象的方法,代理類來幫我們訪問目標類對象,這樣我們就可以在代理類上添加更多需要的擴展功能,而目標類不用改動,只用實現自身的主要功能。 代理類是為了擴展目標類的功能,代理類和目標類的產出結果應該相同,所以為了確保代理類和目標類的 ...
代理模式
目標類和代理類,不是直接調用目標類對象,而是通過調用代理類的對象的方法,代理類來幫我們訪問目標類對象,這樣我們就可以在代理類上添加更多需要的擴展功能,而目標類不用改動,只用實現自身的主要功能。
代理類是為了擴展目標類的功能,代理類和目標類的產出結果應該相同,所以為了確保代理類和目標類的返回類型一致,最好使用介面來約束代理類和目標類。
使用介面而不是繼承,也減少了目標類和代理類間的耦合,並且在動態代理中,動態生成的代理類會自動去繼承 Proxy 類,而Java是單繼承所以不行,而且需要使用反射來獲取目標類的介面來創建代理類實例, 如果被代理對象沒有實現介面,則無法通過介面來定義代理對象需要實現的方法
動態代理
在Java中可以通過Proxy.newProxyInstance()方法創建動態代理類的實例。
而與靜態代理不同的是,靜態是在程式運行前就已經存在代理類的位元組碼文件,也就是說,事先就寫好了代理類的源碼並編譯,動態代理類的源碼是在程式運行期間由JVM根據反射等機制動態的生成。並且目標對象是固定的,代理類一般會持有一個目標類的對象引用(即作為成員變數。
在運行期間動態創建實例
動態代理,通俗點說就是:無需聲明式的創建java代理類,而是在運行過程中生成"虛擬"的代理類,被ClassLoader載入。從而避免了靜態代理那樣需要聲明大量的代理類。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{...}
ClassLoader loader:用於指定一個類載入器,用來載入代理類,通常使用當前類的類載入器
Class<?>[] interfaces:目標類的介面列表,指定生成的代理長什麼樣子,也就是有哪些方法
InvocationHandler h:InvocationHandler是一個介面,所以可以使用匿名內部類並重寫對應方法invoke(),用來指定生成的代理對象要乾什麼事情,在調用代理類的方法時會自動調用該方法。
java動態代理中的invoke方法是如何被自動調用的