1. 程式人生 > >Java裡的靜態代理

Java裡的靜態代理

要用靜態代理,必須有代理類,以及代理類和目標類(要被增強被代理的類)要實現同一個介面。首先我們定義一個介面,裡面有2個方法。

public interface ISomeService {
    public String doMethod1();
    public String doMethod2();
}

接下來是目標類的實現情況:

public class ISomeServiceImpl implements ISomeService {
    @Override
    public String doMethod1() {
        System.out.println("執行1方法");
        return "abc";
    }

    @Override
    public String doMethod2() {
        System.out.println("執行2方法");
        return "def";
    }
}

方法1 和方法2我們都要它們返回小寫的字串,現在需求來了,我們要方法1返回的字串abc變成大寫,方法2返回的字串 def我們再給它後面加上“nihao”。(有前提條件是,我們不可以動目標類,也就是說不能在 ISomeServiceImpl裡改。)

接下來是代理類,我們取名為Proxy,它也要實現以上介面。


public class Proxy implements ISomeService{
    ISomeService target = new ISomeServiceImpl();

    public Proxy(ISomeService target) {
        this.target = target;
    }

    @Override
    public String doMethod1() {
        //呼叫目標方法,該方法返回小寫字母
        System.out.println("在代理增強開始前");
        String result = target.doMethod1();
        result = result.toUpperCase();
        System.out.println("在代理增強結束後");
        //增強目標方法,把小寫字母轉換為大寫字母
        return result ;
    }

    @Override
    public String doMethod2() {

        System.out.println("在代理增強開始前");
        String result = target.doMethod2();
        result = result.concat(" ni hao ");
        System.out.println("在代理增強結束後");
        //增強目標方法,把小寫字母轉換為大寫字母

        return result ;
    }
}

我們從以上程式碼可以看到,我們需要在代理類裡面有目標類的例項,target,把它傳入帶參構造器。這樣就一個代理類和一個目標類對應上了。代理類實現的2個方法裡面,真正執行方法的是目標類例項target,但是我們可以在執行的前後對它進行操作(也就是代理,加強)。如圖上列印“開始前 ”,“開始後”的位置。

接著我們就可以在Test裡面看結果了。

public class MyTest {
    public static void main(String[] args) {
        ISomeService target = new ISomeServiceImpl();
        //目標類物件 target
        ISomeService proxy = new Proxy(target);
        //將target傳入 Proxy的構造器,讓它們對應
        String str1 =  proxy.doMethod1();
        //實質上proxy.doMethod1方法體裡面,是target做了方法1,代理類只是給它加強了。
        System.out.println(str1);
        String str2 =  proxy.doMethod2();
        System.out.println(str2);
    }
}

輸出結果如下:

在代理增強開始前
執行1方法
在代理增強結束後
ABC
在代理增強開始前
執行2方法
在代理增強結束後
def ni hao 

 

靜態代理的缺點1: 因為代理類和目標類要實現同一個介面,所以裡面會有很多程式碼在邏輯上是重複的,另外如果接口裡再增加方法,實現類和代理類也要對應的都增加方法,方法多了過後,會有程式碼冗餘的問題(相同/類似的程式碼過多,讓人感覺很複雜)。

靜態代理的缺點2:我們一個代理類只能代理一個型別的目標類,比如以上例子,我們的Proxy,只能為ISomeServiceImpl服務,如果再有別的類需要代理,我們這個代理類就不能用了,而是得再給別的類,寫一個代理類,再使用。 靜態代理不利於擴充套件。