Java裡的靜態代理
阿新 • • 發佈:2018-11-19
要用靜態代理,必須有代理類,以及代理類和目標類(要被增強被代理的類)要實現同一個介面。首先我們定義一個介面,裡面有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服務,如果再有別的類需要代理,我們這個代理類就不能用了,而是得再給別的類,寫一個代理類,再使用。 靜態代理不利於擴充套件。