JavaSE進(jìn)階

14.7 反射的應(yīng)用:動(dòng)態(tài)代理

14.7.1 Java動(dòng)態(tài)代理

  • 之前為大家講解過代理機(jī)制的操作,屬于靜態(tài)代理,特征是代理類和目標(biāo)對(duì)象的類都是在編譯期間確定下來,不利于程序的擴(kuò)展。同時(shí),每一個(gè)代理類只能為一個(gè)接口服務(wù),這樣一來程序開發(fā)中必然產(chǎn)生過多的代理。
  • 最好可以通過一個(gè)代理類完成全部的代理功能
  • 動(dòng)態(tài)代理是指客戶通過代理類來調(diào)用其它對(duì)象的方法,并且是在程序運(yùn)行時(shí)根據(jù)需要?jiǎng)討B(tài)創(chuàng)建目標(biāo)類的代理對(duì)象。
  • 動(dòng)態(tài)代理使用場(chǎng)合:
    • 調(diào)試
    • 遠(yuǎn)程方法調(diào)用
  • 代理設(shè)計(jì)模式的原理:

???? 使用一個(gè)代理將對(duì)象包裝起來, 然后用該代理對(duì)象取代原始對(duì)象. 任何對(duì)原始對(duì)象的調(diào)用都要通過代理. 代理對(duì)象決定是否以及何時(shí)將方法調(diào)用轉(zhuǎn)到原始對(duì)象上.

  • Proxy :專門完成代理的操作類,是所有動(dòng)態(tài)代理類的父類。通過此類為一個(gè)或多個(gè)接口動(dòng)態(tài)地生成實(shí)現(xiàn)類。
  • 提供用于創(chuàng)建動(dòng)態(tài)代理類和動(dòng)態(tài)代理對(duì)象的靜態(tài)方法
    • static?Class<?> getProxyClass(ClassLoader?loader, Class<?>...?interfaces)? 創(chuàng)建一個(gè)動(dòng)態(tài)代理類所對(duì)應(yīng)的Class對(duì)象
    • static?Object newProxyInstance(ClassLoader?loader, Class<?>[]?interfaces, InvocationHandler?h)? 直接創(chuàng)建一個(gè)動(dòng)態(tài)代理對(duì)象

ClassLoader : 類加載器

Class<?>[] : 得到全部的接口

InvocationHandler : 得到InvocationHandler接口的子類實(shí)例

14.7.2 動(dòng)態(tài)代理步驟

1.創(chuàng)建一個(gè)實(shí)現(xiàn)接口InvocationHandler的類,它必須實(shí)現(xiàn)invoke方法,以完成代理的具體操作。

public Object invoke(Object theProxy, Method method, Object[] params) throws Throwable{

??????? try

??????? {

???????? Object retval = method.invoke(targetObj, params);

???????? // Print out the result

?????????? System.out.println(retval);

??????????? return retval;

??????? }

????? catch (Exception exc){}

Object theProxy : 被代理對(duì)象

Method method : 要調(diào)用的方法

Object[] params : 方法調(diào)用時(shí)所需要的參數(shù)

 

2.創(chuàng)建被代理的類以及接口

3.通過Proxy的靜態(tài)方法

newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 創(chuàng)建一個(gè)Subject接口代理

?? RealSubject target = new RealSubject();

// Create a proxy to wrap the original implementation

?????????? ?DebugProxy proxy = new DebugProxy(target);

?// Get a reference to the proxy through the Subject interface

???????? ?Subject sub = (Subject) Proxy.newProxyInstance(

??????????? Subject.class.getClassLoader(),

??????????? new Class[] { Subject.class }, proxy);

 

4.通過 Subject代理調(diào)用RealSubject實(shí)現(xiàn)類的方法

 

?? ??String info = sub.say(“Peter", 24);

???? System.out.println(info);