java靜態代理與動態代理

来源:http://www.cnblogs.com/orlion/archive/2016/04/03/5350752.html
-Advertisement-
Play Games

原文鏈接:http://www.orlion.ga/207/ 一、代理模式 代理模式是經常用到的設計模式,代理模式是給指定對象提供代理對象。由代理對象來控制具體對象的引用。 代理模式涉及到的角色: 抽象主題角色:聲明瞭代理主題和真實主題的公共介面,使任何需要真實主題的地方都能用代理主題代替。 代理主 ...


原文鏈接:http://www.orlion.ga/207/

一、代理模式

    代理模式是經常用到的設計模式,代理模式是給指定對象提供代理對象。由代理對象來控制具體對象的引用。

    代理模式涉及到的角色:

        抽象主題角色:聲明瞭代理主題和真實主題的公共介面,使任何需要真實主題的地方都能用代理主題代替。

  1.     代理主題角色:含有真實主題的引用,從而可以在任何時候操作真實主題,代理主題功過提供和真實主題相同的介面,使它可以隨時代替真實主題。代理主題通過持有真實主題的引用,不但可以控制真實主題的創建或刪除,可以在真實主題被調用前進行攔截,或在調用後進行某些操作。

       真實代理對象:定義了代理角色所代表的具體對象。

    (設計模式是通用的)

    按照代理創建的時期代理類可以分成兩種:

        靜態代理:由程式員創建或特定工具自動生成源代碼,再對其編譯。在程式運行前,代理類的.class文件就已經存在        了。

        動態代理:在程式運行時,運用反射機制動態創建而成。

    

二、靜態代理

    Talk is cheap,show me the code

    首先定義個酒廠的介面:

    WineFactory.java

    package ml.orlion.proxy;    
    
    public interface WineFactory {
    
    	public void sell();
    }

    然後再定義一個酒廠類實現這個介面:

    WineFactoryImpl.java

    package ml.orlion.proxy;

    public class WineFactoryImpl implements WineFactory{
    
    	@Override
    	public void sell() {
    		System.out.println("賣酒");
    	}
    	
    }

    然後定義一個代理類,對酒廠進行代理:

    WineFactoryProxy.java

    package ml.orlion.proxy;
    /**
     * 代理類
     * 對WineFactoryImpl進行代理
     */
    public class WineFactoryProxy implements WineFactory{
    	
    	private WineFactory winef;
    
    	public WineFactoryProxy(WineFactory winef){
    		this.winef = winef;
    	}
    
    	@Override
    	public void sell() {
    		System.out.println("賣酒之前...");
    		winef.sell();
    		System.out.println("賣酒之後...");
    	}
    }

 

三、動態代理

    由靜態代理的代碼可以看到靜態代理只能對一個介面進行服務,如果項目中有很多個介面,那麼肯定會產生過多的代理。這時候就需要用到動態代理,由一個代理類完成所有的代理功能。動態代理類的位元組碼在程式運行時由Java反射機制動態生成,無需程式員手工編寫它的源代碼。動態代理類不僅簡化了編程工作,而且提高了軟體系統的可擴展性,因為Java 反射機制可以生成任意類型的動態代理類。

    JDK動態代理中包含一個InvocationHandler介面和一個Proxy類

    (1)InvocationHandler介面

    public interface InvocationHandler {     
        public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 
    }

    其中Object porxy:是被代理的對象

    Method method:要調用的方法

    Object[] args:要調用的方法的參數

    (2)Proxy類

    Proxy類是專門完成代理的操作類,可以通過此類為一個或多個介面動態地生成實現類,此類提供瞭如下的操作方法:

    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,     InvocationHandler h)  throws IllegalArgumentException

    其中ClassLoader loader:是類載入器;

    (在java中主要有三種類載入器:

        Booststrap ClassLoader:此載入器採用C++編寫,一般開發中是看不到的;

            Extendsion ClassLoader:用來進行擴展類的載入,一般對應的是jrelibext目錄中的類; 

            AppClassLoader:(預設)載入classpath指定的類,是最常使用的是一種載入器。          

    )

    Class<?>[] interfaces:得到全部介面;

    InvocationHandler h:得到InvocationHandler介面的子類實例;

    code:

     WineFactory.java和WineFactoryImpl.java和靜態代理的代碼相同。

    WineFactoryInvocationHandler.java:

    package ml.orlion.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * JDK動態代理類
     * 對WineFactoryImpl進行代理
     */
    public class WineFactoryInvocationHandler implements InvocationHandler{
    
    	private Object target;
    
    	@Override
    	public Object invoke(Object porxy, Method m, Object[] args) throws Throwable {
    		
    		Object result = null;
    		
    		beforeMethod();
    		// 執行
    		result = m.invoke(target, args);
    		
    		afterMethod();
    		return result;
    	}
    	
    	public void beforeMethod(){
    		System.out.println("賣酒之前...");
    	}
    	
    	public void afterMethod(){
    		System.out.println("賣酒之後...");
    	}
    	
    	public Object getTarget() {
    		return target;
    	}
    
    	public void setTarget(Object target) {
    		this.target = target;
    	}
    }

    測試:

    // 產生一個被代理對象
    WineFactory wf = new WineFactoryImpl();
    // 將被代理對象交給InvocationHandler
    WineFactoryInvocationHandler wfih = new WineFactoryInvocationHandler();
    wfih.setTarget(wf);
    // 根據被代理對象產生一個代理
    WineFactory wfp = (WineFactory)Proxy.newProxyInstance(wf.getClass().getClassLoader(), wf.getClass().getInterfaces(), wfih);
    wfp.sell();

    

    除了JDK動態代理外還有一種cglib動態代理,具體可參考文章(本文參考):http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原文鏈接:http://www.orlion.ga/689/ 好久之前就知道有這麼個東西,但是一直沒用,一直用exit()、var_dump() debug,效率很低。 首先下載xdebug的dll文件(Window環境下)網址是:https://xdebug.org/download.php,此次 ...
  • 原文鏈接:http://www.orlion.ga/776/ 用C寫的程式效率可能不如彙編,而且有些平臺相關的指令必須手寫,例如x86是埠I/O,而c語言就沒有這個概念,所以in/out指令必須用彙編來寫。 gcc提供了一種擴展寫法可以在C代碼中試用內聯彙編,最簡單的格式是__asm__("ass ...
  • 1,在python中#以井號鍵開頭的是註釋的內容,解釋器不會管他; 2,在python中:以冒號結尾時,後面的縮進為其代碼塊,這是約定熟成的習慣,並且堅持一個縮進頂4個空格。(sublime Text設置一個tab頂4個空格:在preference——>seting-user中,在花括弧中添加如下一 ...
  • 基礎知識(包括但不限於:二叉查找樹是啥,SBT又是啥反正又不能吃,平衡樹怎麼旋轉,等等)在這裡就不(lan)予(de)贅(duo)述(xie)了。 由於學生黨比較忙,所以博文寫的比較簡略,有時間會慢慢補完 先貼代碼: 1 int seed; 2 int _rand() 3 { 4 return se ...
  • 2nd
    02.01_Java語言基礎(常量的概述和使用)(掌握) A:什麼是常量 在程式執行的過程中其值不可以發生改變 B:Java中常量的分類 字面值常量 自定義常量(面向對象部分講) C:字面值常量的分類 字元串常量 用雙引號括起來的內容 整數常量 所有整數 小數常量 所有小數 字元常量 用單引號括起來 ...
  • ggg fffffffffffffffffffffffffffffffffffffffffffffff ...
  • 遍歷List的多種方式 在講如何線程安全地遍歷List之前,先看看通常我們遍歷一個List會採用哪些方式。 方式一: 方式二: 方式三: 方式四(Java 8): 方式五(Java 8 Lambda): 首先,方式一的遍歷方法是一種非常不建議使用的方式,特別是對於LinkedList。LinkedL ...
  • 輸出:用print()在括弧中加上字元串,就可以向屏幕上輸出指定的文字。比如輸出'hello, world',用代碼實現如下>>>print('hello,world') 也可以是多個字元串,中間用逗號鏈接‘;代碼實現如下>>>print('The quick bronw fox','jumps o ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...