java代理模式,java代理模式的應用場景

本文目錄一覽:

Java程序性能優化-代理模式(5)

  代理模式( )

在以上代碼中 使用CtField make()方法和CtNewMehod make()方法在運行時生成了代理類的字段和方法 這些邏輯由Javassist的CtClass對象處理 將Java代碼轉換為對應的位元組碼 並生成動態代理類的實例

注意 與靜態代理相比 動態代理可以很大幅度地減少代碼行數 並提升系統的靈活性

在Java中 動態代理類的生成主要涉及對ClassLoader的使用 這裡以CGLIB為例 簡要闡述動態類的加載過程 使用CGLIB生成動態代理 首先需要生成Enhancer類實例 並指定用於處理代理業務的回調類 在Enhancer create()方法中 會使用DefaultGeneratorStrategy Generate()方法生成動態代理類的位元組碼 並保存在byte數組中 接着使用ReflectUtils defineClass()方法 通過反射 調用ClassLoader defineClass()方法 將位元組碼裝載到ClassLoader中 完成類的加載 最後使用ReflectUtils newInstance()方法 通過反射 生成動態類的實例 並返回該實例 無論使用何種方法生成動態代理 雖然實現細節不同 但主要邏輯都如圖 所示

圖   實現動態代理的基本步驟

前文介紹的幾種動態代理的生成方法 性能有一定差異 為了能更好地測試它們的性能 去掉DBQuery類中的sleep()代碼 並使用以下方法測試

public static final int CIRCLE= ;

public static void main(String[] args) throws Exception {

IDBQuery d=null;

long begin=System currentTimeMillis()

d=createJdkProxy()                      //測試JDK動態代理

System out println( createJdkProxy: +(System currentTimeMillis() beg    in))

System out println( JdkProxy class: +d getClass() getName())

begin=System currentTimeMillis()

for(int i= ;iCIRCLE;i++)

d request()

System out println( callJdkProxy: +(System currentTimeMillis() begin    ))

begin=System currentTimeMillis()

d=createCglibProxy()                    //測試CGLIB動態代理

System out println( createCglibProxy: +(System currentTimeMillis() b    egin))

System out println( CglibProxy class: +d getClass() getName())

begin=System currentTimeMillis()

for(int i= ;iCIRCLE;i++)

d request()

System out println( callCglibProxy: +(System currentTimeMillis() beg    in))

begin=System currentTimeMillis()

d=createJavassistDynProxy()             //測試Javaassist動態代理

System out println( createJavassistDynProxy: +(System currentTimeMil    lis() begin))

System out println( JavassistDynProxy class: +d getClass() getName())

begin=System currentTimeMillis()

for(int i= ;iCIRCLE;i++)

d request()

System out println( callJavassistDynProxy: +(System currentTimeMilli    s() begin))

begin=System currentTimeMillis()

d=createJavassistBytecodeDynamicProxy()     //測試Javassist動態代理

System out println( createJavassistBytecodeDynamicProxy: +(System cu    rrentTimeMillis() begin))

System out println( JavassistBytecodeDynamicProxy class: +d getClass()

getName())

begin=System currentTimeMillis()

for(int i= ;iCIRCLE;i++)

d request()

System out println( callJavassistBytecodeDynamicProxy: +(System curr    entTimeMillis() begin))

}

       返回目錄 Java程序性能優化 讓你的Java程序更快 更穩定

編輯推薦

       Java程序設計培訓視頻教程

       J EE高級框架實戰培訓視頻教程

       J ME移動開發實戰教學視頻

Visual C++音頻/視頻技術開發與實戰

Oracle索引技術

lishixinzhi/Article/program/Java/gj/201311/27830

Java設計模式之Proxy模式

為什麼要使用Proxy?

授權機制 不同級別的用戶對同一對象擁有不同的訪問權利 如Jive 論壇系統中 就使用Proxy 進行授權機制控制 訪問論壇有兩種人:註冊用戶和遊客(未註冊用戶) Jive 中就通過類似ForumProxy 這樣的代理來控制這兩種用戶對論壇的訪問權限

某個客戶端不能直接操作到某個對象 但又必須和那個對象有所互動

舉例兩個具體情況:

( )如果那個對象是一個是很大的圖片 需要花費很長時間才能顯示出來 那麼當這個圖片包含在文檔中時 使用編輯器或瀏覽器打開這個文檔 打開文檔必須很迅速 不能等待大圖片處理完成 這時需要做個圖片Proxy 來代替真正的圖片

( )如果那個對象在Internet 的某個遠端服務器上 直接操作這個對象因為網絡速度原因可能比較慢 那我們可以先用Proxy 來代替那個對象

總之原則是 對於開銷很大的對象 只有在使用它時才創建 這個原則可以為我們節省很多寶貴的Java 內存 所以 有些人認為Java 耗費資源內存 我以為這和程序編製思路也有一定的關係

如何使用Proxy?

以Jive 論壇系統為例 訪問論壇系統的用戶有多種類型:註冊普通用戶 論壇管理者 系統管理者 遊客 註冊普通用戶才能發言;論壇管理者可以管理他被授權的論壇;系統管理者可以管理所有事務等 這些權限劃分和管理是使用Proxy 完成的

Forum 是Jive 的核心接口 在Forum 中陳列了有關論壇操作的主要行為 如論壇名稱 論壇描述的獲取和修改 帖子發表刪除編輯等

在ForumPermissions 中定義了各種級別權限的用戶:

public class ForumPermissions implements Cacheable {

/*** Permission to read object */

public static final int READ = ;

/*** Permission to administer the entire sytem */

public static final int SYSTEM_ADMIN = ;

/*** Permission to administer a particular forum */

public static final int FORUM_ADMIN = ;

/*** Permission to administer a particular user */

public static final int USER_ADMIN = ;

/*** Permission to administer a particular group */

public static final int GROUP_ADMIN = ;

/*** Permission to moderate threads */

public static final int MODERATE_THREADS = ;

/*** Permission to create a new thread */

public static final int CREATE_THREAD = ;

/*** Permission to create a new message */

public static final int CREATE_MESSAGE = ;

/*** Permission to moderate messages */

public static final int MODERATE_MESSAGES = ;

public boolean isSystemOrForumAdmin() {

return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);

}

}

因此 Forum 中各種操作權限是和ForumPermissions 定義的用戶級別有關係的 作為接口Forum 的實現:ForumProxy 正是將這種對應關係聯繫起來 比如 修改Forum 的名稱 只有論壇管理者或系統管理者可以修改 代碼如下:

public class ForumProxy implements Forum {

private ForumPermissions permissions;

private Forum forum;

this authorization = authorization;

public ForumProxy(Forum forum Authorization authorization

ForumPermissions permissions)

{

this forum = forum;

this authorization = authorization;

this permissions = permissions;

}

public void setName(String name) throws UnauthorizedException

ForumAlreadyExistsException

{

//只有是系統或論壇管理者才可以修改名稱

if (permissions isSystemOrForumAdmin()) {

forum setName(name);

}

else {

throw new UnauthorizedException();

}

}

}

而DbForum 才是接口Forum 的真正實現 以修改論壇名稱為例:

public class DbForum implements Forum Cacheable {

public void setName(String name) throws

ForumAlreadyExistsException {

this name = name;

//這裡真正將新名稱保存到數據庫中

saveToDb();

}

}

凡是涉及到對論壇名稱修改這一事件 其他程序都首先得和ForumProxy 打交道 由ForumProxy 決定是否有權限做某一樣事情 ForumProxy 是個名副其實的 網關 安全代理系統

我們已經知道 使用Forum 需要通過ForumProxy Jive 中創建一個Forum 是使用Factory 模式 有一個總的抽象類ForumFactory 在這個抽象類中 調用ForumFactory 是通過getInstance()方法實現 這裡使用了Singleton getInstance()返回的是ForumFactoryProxy

為什麼不返回ForumFactory 而返回ForumFactory 的實現ForumFactoryProxy?

原因是明顯的 需要通過代理確定是否有權限創建forum

在ForumFactoryProxy 中我們看到代碼如下:

public class ForumFactoryProxy extends ForumFactory {

protected ForumFactory factory;

protected Authorization authorization;

protected ForumPermissions permissions;

public ForumFactoryProxy(Authorization authorization ForumFactory factory

ForumPermissions permissions)

{

this factory = factory;

this authorization = authorization;

this permissions = permissions;

}

public Forum createForum(String name String description)

throws UnauthorizedException ForumAlreadyExistsException

{

//只有系統管理者才可以創建forum

if (permissions get(ForumPermissions SYSTEM_ADMIN)) {

Forum newForum = factory createForum(name description);

return new ForumProxy(newForum authorization permissions);

}

else {

throw new UnauthorizedException();

}

}

方法createForum 返回的也是ForumProxy Proxy 就象一道牆 其他程序只能和Proxy 交互操作

注意到這裡有兩個Proxy:ForumProxy 和ForumFactoryProxy 代表兩個不同的職責:使用Forum 和創建Forum;

至於為什麼將使用對象和創建對象分開 這也是為什麼使用Factory 模式的原因所在:是為了 封裝 分派 ;換句話說 儘可能功能單一化 方便維護修改

以上我們討論了如何使用Proxy 進行授權機制的訪問 Proxy 還可以對用戶隱藏另外一種稱為copy on write 的優化方式 拷貝一個龐大而複雜的對象是一個開銷很大的操作 如果拷貝過程中 沒有對原來的對象有所修改 那麼這樣的拷貝開銷就沒有必要 用代理延遲這一拷貝過程

比如:我們有一個很大的Collection 具體如hashtable 有很多客戶端會並發同時訪問它

其中一個特別的客戶端要進行連續的數據獲取 此時要求其他客戶端不能再向hashtable 中增加或刪除 東東

最直接的解決方案是:使用collection 的lock 讓這特別的客戶端獲得這個lock 進行連續的數據獲取 然後再釋放lock

public void foFetches(Hashtable ht){

synchronized(ht){

//具體的連續數據獲取動作

}

}

但是這一辦法可能鎖住Collection 會很長時間 這段時間 其他客戶端就不能訪問該Collection 了

第二個解決方案是clone 這個Collection 然後讓連續的數據獲取針對clone 出來的那個Collection 操作 這個方案前提是 這個Collection 是可clone 的 而且必須有提供深度clone 的方法 Hashtable 就提供了對自己的clone 方法 但不是Key 和value 對象的clone 關於Clone 含義可以參考專門文章

public void foFetches(Hashtable ht){

Hashttable newht=(Hashtable)ht clone();

}

問題又來了 由於是針對clone 出來的對象操作 如果原來的母體被其他客戶端操作修改了 那麼對clone 出來的對象操作就沒有意義了

最後解決方案:我們可以等其他客戶端修改完成後再進行clone 也就是說 這個特別的客戶端先通過調用一個叫clone 的方法來進行一系列數據獲取操作 但實際上沒有真正的進行對象拷貝 直至有其他客戶端修改了這個對象Collection

lishixinzhi/Article/program/Java/gj/201311/27422

Java代理的作用和實現?

代理模式的作用是:為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個客戶不想或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。

Java靜態代理和iOS代理模式這兩個概念的理解上的疑惑

看了JAVA版的設計模式的 代理模式 和IOS @protrol 比較,java 的看了都暈了。不完全一致,委託和代理 稱呼上就好像反的。用JAVA 的中接口 在view中實現方法,就要把接口中所有的方法都複寫一下,這個不太好用, 還不知道其它什麼模式來實現像Ios @protrol 的功能。

java中的代理是什麼意思?

代理模式在設計模式中的定義就是:為其他對象提供一種代理以控制對這個對象的訪問。說白了就是,在一些情況下客戶不想或者不能直接引用一個對象,而代理對象可以在客戶和目標對象之間起到中介作用,去掉客戶不能看到的內容和服務或者增添客戶需要的額外服務。

原創文章,作者:KZKR,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/137554.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
KZKR的頭像KZKR
上一篇 2024-10-04 00:17
下一篇 2024-10-04 00:17

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Unity3D 創建沒有 Terrain Tile 的場景

    這篇文章將會介紹如何在 Unity3D 中創建一個沒有 Terrain Tile 的場景,同時也讓讀者了解如何通過編程實現這個功能。 一、基礎概念 在 Unity3D 中,Terr…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發佈。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字符串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字符串中是否存在多個指定字符: 一、字符串遍歷 字符串是Java編程中非常重要的一種數據類型。要判斷字符串中是否存在多個指定字符…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29
  • Java任務下發回滾系統的設計與實現

    本文將介紹一個Java任務下發回滾系統的設計與實現。該系統可以用於執行複雜的任務,包括可回滾的任務,及時恢復任務失敗前的狀態。系統使用Java語言進行開發,可以支持多種類型的任務。…

    編程 2025-04-29

發表回復

登錄後才能評論