本文目錄一覽:
- 1、Java程序性能優化-代理模式(5)
- 2、Java設計模式之Proxy模式
- 3、Java代理的作用和實現?
- 4、Java靜態代理和iOS代理模式這兩個概念的理解上的疑惑
- 5、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-tw/n/137554.html