|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
| 上一個類別 下一個類別 | 框架 無框架 | |||||||||
| 摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 | |||||||||
java.lang.Objectjava.lang.reflect.Proxy
public class Proxy
Proxy 提供用於創建動態代理類別和實例的靜態方法,它還是由這些方法創建的所有動態代理類別的父級類別。
創建某一介面 Foo 的代理:
InvocationHandler handler = new MyInvocationHandler(...);
Class proxyClass = Proxy.getProxyClass(
Foo.class.getClassLoader(), new Class[] { Foo.class });
Foo f = (Foo) proxyClass.
getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });
或使用以下更簡單的方法:
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
handler);
動態代理類別(以下簡稱為代理類別)是一個實作在創建類別時在運行時指定的介面列表的類別,該類別具有下面描述的行為。
代理介面 是代理類別實作的一個介面。
代理實例 是代理類別的一個實例。
每個代理實例都有一個關聯的調用處理程序 物件,它可以實作介面 InvocationHandler。通過其中一個代理介面的代理實例上的方法調用將被指派到實例的調用處理程序的 Invoke 方法,並傳遞代理實例、識別調用方法的 java.lang.reflect.Method 物件以及包含參數的 Object 型別的陣列。調用處理程序以適當的方式處理編碼的方法調用,並且它返回的結果將作為代理實例上方法調用的結果返回。
代理類別具用以下屬性:
"$Proxy" 開頭的類別名空間應該為代理類別保留。
java.lang.reflect.Proxy。
Class 物件調用 getInterfaces 將返回一個套件含相同介面列表的陣列(按其創建時指定的順序),對其 Class 物件調用 getMethods 將返回一個套件括這些介面中所有方法的 Method 物件的陣列,並且調用 getMethod 將會在代理介面中找到期望的一些方法。
Proxy.isProxyClass 方法傳遞代理類別(由 Proxy.getProxyClass 返回的類別,或由 Proxy.newProxyInstance 返回的物件的類別),則該方法返回 true,否則返回 false。
java.security.ProtectionDomain 與由引導類別載入器(如 java.lang.Object)載入的系統類別相同,原因是代理類別的程式碼由受信任的系統程式碼產生。此保護域通常被授予 java.security.AllPermission。
InvocationHandler 的實作)的公共建構子,用於設置代理實例的調用處理程序。並非必須使用反射 API 才能存取公共建構子,通過調用 Proxy.newInstance 方法(將調用 Proxy.getProxyClass 的操作和調用帶有調用處理程序的建構子結合在一起)也可以創建代理實例。
代理實例具有以下屬性:
proxy 和一個由其代理類別 Foo 實作的介面,以下表達式將返回 true:
proxy instanceof Foo
並且以下的強制轉換操作將會成功(而不拋出 ClassCastException):
(Foo) proxy
Proxy.getInvocationHandler 方法將返回與作為其參數傳遞的代理實例相關的調用處理程序。
Invoke 方法。
java.lang.Object 中宣告的 hashCode、equals 或 toString 方法的調用將按照與編碼和指派介面方法調用相同的方式進行編碼,並被指派到調用處理程序的 invoke 方法,如上所述。傳遞到 invoke 的 Method 物件的宣告類別是 java.lang.Object。代理類別不覆寫從 java.lang.Object 繼承的代理實例的其他公共方法,所以這些方法的調用行為與其對 java.lang.Object 實例的操作一樣。
當代理類別的兩個或多個介面包含一個具有相同名稱和參數簽章的方法時,代理類別的介面順序變得非常重要。在代理實例上調用重複方法 時,傳遞到調用處理程序的 Method 物件沒有必要成為其宣告類別可以從介面(通過該介面調用代理方法)的參考型別指派的物件。此限制存在的原因是,產生的代理類別中的相應方法實作無法確定它通過哪一個介面調用。因此,在代理實例上調用重複方法時,第一個介面中的方法的 Method 物件包含介面的代理類別列表中的方法(直接或通過父級介面繼承),該物件會傳遞到調用處理程序的 invoke 方法,無論該方法調用通過哪一種參考型別發生。
如果代理介面包含某一方法,它的名稱和參數簽章與 java.lang.Object 的 hashCode、equals 或 toString 方法相同,那麼在代理實例上調用這樣的方法時,傳遞到調用處理程序的 Method 物件將使 java.lang.Object 成為其宣告類別。換句話說,java.lang.Object 公共的非最終方法理論上在所有代理介面之前,以便確定哪一個 Method 物件傳遞到調用處理程序。
還要注意,當重複方法被指派到調用處理程序時,invoke 方法只可以拋出經過檢查的異常型別,該異常型別可以使用所有 代理介面(可以通過它調用)中方法的 throws 子句指派一種異常型別。如果 invoke 方法拋出一個經過檢查的異常,該異常沒有指派給任何由一個代理介面(可以通過它調用)中的方法宣告的異常型別,那麼該代理實例上的調用將拋出一個未經檢查的 UndeclaredThrowableException。此限製表示並非所有的由傳遞到 invoke 方法的 Method 物件上調用 getExceptionTypes 返回的異常型別都可以由 invoke 方法成功拋出。
InvocationHandler,
序列化表格| 欄位摘要 | |
|---|---|
protected InvocationHandler |
h
此代理實例的調用處理程序。 |
| 建構子摘要 | |
|---|---|
protected |
Proxy(InvocationHandler h)
使用其調用處理程序的指定值從子類別(通常為動態代理類別)建構新的 Proxy 實例。 |
| 方法摘要 | |
|---|---|
static InvocationHandler |
getInvocationHandler(Object proxy)
返回指定代理實例的調用處理程序。 |
static Class<?> |
getProxyClass(ClassLoader loader,
Class<?>... interfaces)
返回代理類別的 java.lang.Class 物件,並向其提供類別載入器和介面陣列。 |
static boolean |
isProxyClass(Class<?> cl)
當且僅當指定的類別通過 getProxyClass 方法或 newProxyInstance 方法動態產生為代理類別時,返回 true。 |
static Object |
newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
返回一個指定介面的代理類別實例,該介面可以將方法調用指派到指定的調用處理程序。 |
| 從類別 java.lang.Object 繼承的方法 |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| 欄位詳細資訊 |
|---|
protected InvocationHandler h
| 建構子詳細資訊 |
|---|
protected Proxy(InvocationHandler h)
Proxy 實例。
h - 此代理實例的調用處理程序| 方法詳細資訊 |
|---|
public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces)
throws IllegalArgumentException
java.lang.Class 物件,並向其提供類別載入器和介面陣列。該代理類別將由指定的類別載入器定義,並將實作提供的所有介面。如果類別載入器已經定義了具有相同排列介面的代理類別,那麼現有的代理類別將被返回;否則,類別載入器將動態產生並定義這些介面的代理類別。
對可以傳遞給 Proxy.getProxyClass 的參數有以下幾個限制:
interfaces 陣列中的所有 Class 物件必須表示介面,而不能表示類別或基本型別。
interfaces 陣列中的兩個元素不能參考同一 Class 物件。
cl 和所有介面 i,以下表達式必須為 true:
Class.forName(i.getName(), false, cl) == i
interfaces 陣列的大小必須不超過 65535。
如果違反了這些限制,Proxy.getProxyClass 將拋出 IllegalArgumentException。如果 interfaces 陣列參數或其任何元素為 null,則將拋出 NullPointerException。
注意,指定的代理介面的順序非常重要:對介面組合相同但順序不同的代理類別的兩個請求會導致兩個不同的代理類別。
loader - 定義代理類別的類別載入器interfaces - 代理類別要實作的介面列表
IllegalArgumentException - 如果違反傳遞到 getProxyClass 的參數上的任何限制
NullPointerException - 如果 interfaces 陣列參數或其任何元素為 null
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
Proxy.getProxyClass(loader, interfaces).
getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });
Proxy.newProxyInstance 拋出 IllegalArgumentException,原因與 Proxy.getProxyClass 相同。
loader - 定義代理類別的類別載入器interfaces - 代理類別要實作的介面列表h - 指派方法調用的調用處理程序
IllegalArgumentException - 如果違反傳遞到 getProxyClass 的參數上的任何限制
NullPointerException - 如果 interfaces 陣列參數或其任何元素為 null,或如果調用處理程序 h 為 nullpublic static boolean isProxyClass(Class<?> cl)
getProxyClass 方法或 newProxyInstance 方法動態產生為代理類別時,返回 true。
此方法的可靠性對於使用它做出安全決策而言非常重要,所以此方法的實作不應僅測試相關的類別是否可以擴展 Proxy。
cl - 要測試的類別
true,否則為 false
NullPointerException - 如果 cl 為 null
public static InvocationHandler getInvocationHandler(Object proxy)
throws IllegalArgumentException
proxy - 返回調用處理程序的代理實例
IllegalArgumentException - 如果參數不是一個代理實例
|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
| 上一個類別 下一個類別 | 框架 無框架 | |||||||||
| 摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 | |||||||||
版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only。