1. 程式人生 > >java代理模式以及實現

java代理模式以及實現

概念
代理(Proxy)是一種設計模式,提供了對目標物件另外的訪問方式;即通過代理物件訪問目標物件。
使用圖表表示如下:
這裡寫圖片描述
目的
在目標物件實現的基礎上,增強額外的功能操作,即擴充套件目標物件的功能。
使用場景
但需要對現有的程式碼增加新的功能時,如果直接在原有程式碼上修改,一方面要熟悉之前的程式碼,另外修改的程式碼還可能帶來新的問題。因此這時代理模式就可以很好的解決這個問題:不修改之前已經寫好的程式碼或者方法,通過代理的方式對該方法進行功能拓展。

兩種代理模式
1 靜態代理
關鍵點
使用者訪問的是目標物件的代理物件,目標物件與代理物件實現同一介面或繼承同一父類,且代理物件中持有目標物件。
舉例如下


使用者(User)去買東西(buy),如果自己去市場買,那麼花費說要購買物品的價格即可;如果不想跑遠,只想到樓下的小商鋪那裡買,那人家就要收取點福利了。。。。
程式碼實現
買東西介面:

public interface IBuy {
    void buy(long money);
}

買東西的使用者,實現這個買的介面:

public class User implements IBuy {
    @Override
    public void buy(long money) {
        System.out.println("買東西,一共花了"+ money+"元!"
); } }

然後呢,樓下小商鋪代理,幫使用者從市場把東西買來了,那麼就要收點福利。。所以樓下小商鋪代理也具有買這個功能:

public class UserProxy implements IBuy {
    private IBuy mIBuy; // 真實代理的物件

    public UserProxy(IBuy IBuy) {
        mIBuy = IBuy;
    }

    @Override
    public void buy(long money) {
        long fee = (long) (money * 0.01); // 代理物件的一些附加福利
System.out.println("靜態代理中介,坑了" + fee + "中介費!"); mIBuy.buy(money + fee); // 真實物件執行 } }

然後是我們的測試程式碼:

    @Test
    public void buy() {
        IBuy user = new User();
        user.buy(10000);

        IBuy userProxy = new UserProxy(user);
        userProxy.buy(10000);
    }

執行,測試,輸出如下結果:
這裡寫圖片描述
可以看到,第一行輸出是使用者直接購買物品說需要花費的錢,下面兩行是使用者使用了小商鋪這種代理,來購買東西,所需要付給小商鋪的福利,以及一共花費的金額。

這就是靜態代理模式的實現,從實現上看,代理物件的確沒有對目標物件的程式碼做修改,只是在目標物件功能的基礎上,添加了一些其他的附加功能;並且從代理物件中持有目標物件這一設計可以看出,代理物件可以完全控制目標物件的功能是否執行。但是,從中我們也可以看出靜態代理模式也存在下面這個缺點:

代理物件需要與目標物件實現一樣的介面,所以會有很多代理類,類太多.同時,一旦介面增加方法,目標物件與代理物件都要維護.

所以既然有靜態代理,那麼對應的應該也有個動態代理,不知道動態代理能不能解決這個缺點呢?

1 動態代理
關鍵點
1.代理物件,需要實現JDK中的介面:InvocationHandler,並實現方法invoke;
2.代理物件的生成,是利用JDK的API,程式執行時生成,動態的在記憶體中構建代理物件(需要我們指定建立代理物件/目標物件實現的介面的型別)
3.動態代理也叫做:JDK代理,介面代理
JDK api介紹
JDK中生成代理物件的API
代理類所在包:java.lang.reflect.Proxy
JDK實現代理只需要使用newProxyInstance方法,但是該方法需要接收三個引數,完整的寫法是:

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

ClassLoader loader:當前目標物件的類載入器
Class<>[] interfaces:目標物件實現的介面的型別,使用泛型方式確認型別
InvocationHandler h:實現了InvocationHandler介面的代理物件

程式碼實現
動態代理物件:

public class DProxy implements InvocationHandler {
    private IBuy mBuy; // 持有的目標物件

    public DProxy(IBuy buy) {
        mBuy = buy;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("buy")) {
            long money = (long) args[0];
            long fee = (long) (money * 0.02);
            System.out.println("動態代理中介,坑了" + fee + "中介費!");
            long newMoney = money + fee;
            args[0] = newMoney;
            return method.invoke(mBuy, args);
        }
        return null;
    }
}

程式碼中,由於我們知道介面實現的名稱以及介面引數,所以在invoke中,我們直接對buy方法進行了額外的功能新增,如果不知道介面對應的名稱以及介面引數,那麼可以直接使用反射的方法執行method對應的invoke方法:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("附加功能1");
                        //執行目標物件方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("附加功能2");
                        return returnValue;
                    }

然後呢,是我們的測試程式碼:

    @Test
    public void buy() {
        IBuy user = new User();
        user.buy(10000);

        IBuy userProxy = new UserProxy(user);
        userProxy.buy(10000);

        IBuy dProxy = (IBuy) Proxy.newProxyInstance(user.getClass().getClassLoader(),user.getClass().getInterfaces(),new DProxy(user));
        dProxy.buy(10000);
    }

最終的執行結果:
這裡寫圖片描述

總結:動態代理的invoke方法中,是利用反射的方法來執行介面中的method方法的,所以無論介面中的方法增加還是減少,都不影響動態代理的invoke方法執行,因而可以解決靜態代理中的問題。另外,動態代理的目標物件需要實現某一介面,這樣動態代理才可以代理該物件。

相關推薦

java代理模式以及實現

概念 代理(Proxy)是一種設計模式,提供了對目標物件另外的訪問方式;即通過代理物件訪問目標物件。 使用圖表表示如下: 目的 在目標物件實現的基礎上,增強額外的功能操作,即擴充套件目標物件的功能。 使用場景 但需要對現有的程式碼增加新的功能時,

java 代理模式實現及應用

java 代理模式代理(Proxy)是一種設計模式,提供了對目標物件另外的訪問方式;即通過代理物件訪問目標物件.這樣做的好處是:可以在目標物件實現的基礎上,增強額外的功能操作,即擴充套件目標物件的功能1.靜態代理靜態代理在使用時,需要定義介面或者父類,被代理物件與代理物件一起

Java靜態代理與動態代理模式實現

loader 兩個 如何 圖片 ide 相同 catch 規範 png 前言: 在現實生活中,考慮以下的場景:小王打算要去租房,他相中了一個房子,準備去找房東洽談相關事宜。但是房東他很忙,平時上班沒時間,總沒有時間見面,他也沒辦法。後來,房東想了一個辦法,他找到了一個

java三種代理模式實現

1、什麼是代理模式 代理模式:就是為其他物件提供一種代理以控制對這個物件的訪問。 代理可以在不改動目標物件的基礎上,增加其他額外的功能(擴充套件功能)。 舉個例子來說明代理的作用: 一般我們想邀請明星來當我們的代言人,我們並不能直接聯絡到明星,而是通過其經紀人,來告訴經紀人我們需要

Java代理模式實現的三種方式

1.靜態代理 1.1.定義一個介面 public interface IWorkerService { void doSomething(); } 1.2.定義一個實現 public class WorkerServiceImpl implements

Java代理模式及應用(三)Cglib實現

前一節所說的靜態代理和動態代理模式都是要求目標物件是實現一個介面的目標物件,但是有時候目標物件只是一個單獨的物件,並沒有實現任何的介面,這個時候就可以使用以目標物件子類的方式類實現代理,這種方法就叫做:Cglib代理 1.Cglib說明 Cglib代理,

Java代理模式實現與原理詳解(一)

關於Java中的代理,我們首先需要了解的是一種常用的設計模式——代理模式,而對於代理,可根據代理類建立的時間點,分為靜態代理和動態代理。今天我們先來了解一下Java中的靜態代理。 1 代理模式 代理模式是一種常用的設計模式,百度百科中對其定義為:為其他物件提供一個代理以控制對某個物件的訪問。

設計模式代理模式 c++實現以及詳解

proxy模式 <1> 作用:為其他物件提供一種代理以控制對這個物件的訪問。 <2> 代理模式的應用場景:如果已有的方法在使用的時候需要對原有的方法進行改進,此時有兩種辦法:1、修改原有的方法來適應。這樣違反了“對擴充套件開放,對修改關閉”的原則。2

Java 代理模式

all object 控制 cglib動態代理 per 使用 sets back 概念 代理模式的概念:為其他對象提供一種代理一控制對這個對象的訪問。 應用場景:在開發中一些業務類中方法,除了需求的操作,還需要進行其他的非業務操作。比如提供給app的接口。除

Java代理模式的理解

java proxy 代理 反射 Java的代理分為靜態代理和動態代理。靜態代理模式的構成:1.一個共同的接口或抽象類 2.真實的類 3.代理類其中真實類和代理類都實現了那個共同的接口,代理類內部有一個對真實類對象的引用,用戶使用代理類時,實際會調用真實對象的對應方法。靜態代理的局限在於 1.

java代理模式與裝飾者模式

對象 tro 來看 彈性 java代理 question 設計模式 ava 設計 靜態代理和裝飾者模式的區別:   先來看一下裝飾者模式的定義:裝飾者模式動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。   總結一下采用裝飾者模式是為了增強或拓

java 代理模式(靜態代理、動態代理、Cglib代理) 轉載

cas 代理人 缺點 intercept 必須 lan itcast 技術 有時 Java的三種代理模式 1.代理模式 代理(Proxy)是一種設計模式,提供了對目標對象另外的訪問方式;即通過代理對象訪問目標對象.這樣做的好處是:可以在目標對象實現的基礎上,增強額外的功能操

java代理模式詳解

之前 OS 另一個 string nds quest blog abs oid java代理模式詳解 1. 代理模式 代理模式的作用是:為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個客戶不想或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象

java代理模式

nal dos log model 小夥伴 ams stp 變化 dna 事例 小張是一個普普通通的碼農,每天勤勤懇懇地碼代碼。某天中午小張剛要去吃飯,一個電話打到了他的手機上。“是XX公司的小張嗎?我是YY公司的王AA”。“哦,是王總啊,有什麽事情嗎?”。溝通過後,小張弄

代理模式實現

loader 方法參數 測試 food err pro sta 控制 tcl 代理對象和委托對象繼承相同接口,並控制外部對委托對象的訪問。 1. 靜態代理: 代理對象在編譯期確定。 接口(Human): public interface Human{ publ

代理模式C++實現

#include <iostream> #include <string&

設計模式代理模式簡單實現

簡介 代理模式通常用於達到對原有系統功能進行擴充的目的,比如:你剛接手一個別人沒有完成的專案,這時你不想動別人原來的程式碼,還需要新增新功能。這時代理模式,這時代理模式會很好的幫我們解決問題 代理模式一般分為靜態代理,動態代理兩種 靜態代理 靜態代理一般是

Java序列化以及實現

Java 序列化技術可以使你將一個物件的狀態寫入一個Byte 流裡,並且可以從其它地方把該Byte 流裡的資料讀出來,重新構造一個相同的物件。這種機制允許你將物件通過網路進行傳播,並可以隨時把物件持久化到資料庫、檔案等系統裡。Java的序列化機制是RMI、EJB等技術的

Java代理模式(Cplig)代理模式

package ProxyCglib; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.Met

java代理模式學習,靜態代理,JDK動態代理,CGLIB動態代理

                java代理模式學習,靜態代理,JDK動態代理,CGLIB動態代理   一、理解代理 1、代理,Proxy 。意思是:本來該你做的事兒,別人代替你去做。 比如說:即將