代理模式
??代理模式的定義:給某一個(gè)對(duì)象提供一個(gè)代理,并由代理對(duì)象控制對(duì)原對(duì)象的引用。
??代理(Proxy)是一種設(shè)計(jì)模式,提供了對(duì)目標(biāo)對(duì)象另外的訪問(wèn)方式;即通過(guò)代理對(duì)象訪問(wèn)目標(biāo)對(duì)象。這樣做的好處是:可以在目標(biāo)對(duì)象實(shí)現(xiàn)的基礎(chǔ)上,增強(qiáng)額外的功能操作,即擴(kuò)展目標(biāo)對(duì)象的功能。
??這里使用到編程中的一個(gè)思想:不要隨意去修改別人已經(jīng)寫好的代碼或者方法,如果需改修改,可以通過(guò)代理的方式來(lái)擴(kuò)展該方法。
??舉個(gè)例子來(lái)說(shuō)明代理的作用:假設(shè)我們想邀請(qǐng)一位明星,那么并不是直接聯(lián)系明星,而是聯(lián)系明星的經(jīng)紀(jì)人,來(lái)達(dá)到同樣的目的。明星就是一個(gè)目標(biāo)對(duì)象,他只要負(fù)責(zé)活動(dòng)中的節(jié)目,而其他瑣碎的事情就交給他的代理人(經(jīng)紀(jì)人)來(lái)解決。這就是代理思想在現(xiàn)實(shí)中的一個(gè)例子。

??代理模式的關(guān)鍵點(diǎn)是:代理對(duì)象與目標(biāo)對(duì)象。代理對(duì)象是對(duì)目標(biāo)對(duì)象的擴(kuò)展,并會(huì)調(diào)用目標(biāo)對(duì)象。
??代理模式包含如下角色:
??ISubject:抽象主題角色,是一個(gè)接口。該接口是對(duì)象和它的代理共用的接口。
??RealSubject:真實(shí)主題角色,是實(shí)現(xiàn)抽象主題接口的類。
??Proxy:代理角色,內(nèi)部含有對(duì)真實(shí)對(duì)象RealSubject的引用,從而可以操作真實(shí)對(duì)象。代理對(duì)象提供與真實(shí)對(duì)象相同的接口,以便在任何時(shí)刻都能代替真實(shí)對(duì)象。同時(shí),代理對(duì)象可以在執(zhí)行真實(shí)對(duì)象操作時(shí),附加其他的操作,相當(dāng)于對(duì)真實(shí)對(duì)象進(jìn)行封裝。
??代理模式的應(yīng)用:
??遠(yuǎn)程代理:也就是為一個(gè)對(duì)象在不同的地址空間提供局部代表。這樣可以隱藏一個(gè)對(duì)象存在于不同地址空間的事實(shí)。
??虛擬代理:是根據(jù)需要?jiǎng)?chuàng)建開銷很大的對(duì)象。通過(guò)它來(lái)存放實(shí)例化需要很長(zhǎng)時(shí)間的真實(shí)對(duì)象。
??安全代理:用來(lái)控制真實(shí)對(duì)象訪問(wèn)時(shí)的權(quán)限。
??智能代理:是指當(dāng)調(diào)用真實(shí)的對(duì)象時(shí),代理處理一些另外的事情。
??一般將代理分類的話,可分為靜態(tài)代理和動(dòng)態(tài)代理兩種。
靜態(tài)代理
??靜態(tài)代理比較簡(jiǎn)單,是由程序員編寫的代理類,并在程序運(yùn)行前就編譯好的,而不是由程序動(dòng)態(tài)產(chǎn)生代理類,這就是所謂的靜態(tài)。
??考慮這樣的場(chǎng)景,管理員在網(wǎng)站上執(zhí)行操作,在生成操作結(jié)果的同時(shí)需要記錄操作日志,這是很常見的。此時(shí)就可以使用代理模式,代理模式可以通過(guò)聚合和繼承兩種方式實(shí)現(xiàn):
/**
* @Description: 抽象主題接口
* @author: zxt
* @time: 2018年7月7日 下午2:29:46
*/
public interface Manager {
public void doSomething();
}
/**
* @Description: 真實(shí)的主題類
* @author: zxt
* @time: 2018年7月7日 下午2:31:21
*/
public class Admin implements Manager {
@Override
public void doSomething() {
System.out.println("這是真實(shí)的主題類:Admin doSomething!!!");
}
}
/**
* @Description: 以聚合的方式實(shí)現(xiàn)代理主題
* @author: zxt
* @time: 2018年7月7日 下午2:37:08
*/
public class AdminPoly implements Manager {
// 真實(shí)主題類的引用
private Admin admin;
public AdminPoly(Admin admin) {
this.admin = admin;
}
@Override
public void doSomething() {
System.out.println("聚合方式實(shí)現(xiàn)代理:Admin操作開始?。?);
admin.doSomething();
System.out.println("聚合方式實(shí)現(xiàn)代理:Admin操作結(jié)束?。?);
}
}
/**
* @Description: 繼承方式實(shí)現(xiàn)代理
* @author: zxt
* @time: 2018年7月7日 下午2:40:39
*/
public class AdminProxy extends Admin {
@Override
public void doSomething() {
System.out.println("繼承方式實(shí)現(xiàn)代理:Admin操作開始??!");
super.doSomething();
System.out.println("繼承方式實(shí)現(xiàn)代理:Admin操作結(jié)束??!");
}
}
public static void main(String[] args) {
// 1、聚合方式的測(cè)試
Admin admin = new Admin();
Manager manager = new AdminPoly(admin);
manager.doSomething();
System.out.println("============================");
// 2、繼承方式的測(cè)試
AdminProxy proxy = new AdminProxy();
proxy.doSomething();
}
??聚合實(shí)現(xiàn)方式中代理類聚合了被代理類,且代理類及被代理類都實(shí)現(xiàn)了同一個(gè)接口,可實(shí)現(xiàn)靈活多變。繼承式的實(shí)現(xiàn)方式則不夠靈活。
??比如,在管理員操作的同時(shí)需要進(jìn)行權(quán)限的處理,操作內(nèi)容的日志記錄,操作后數(shù)據(jù)的變化三個(gè)功能。三個(gè)功能的排列組合有6種,也就是說(shuō)使用繼承要編寫6個(gè)繼承了Admin的代理類,而使用聚合,僅需要針對(duì)權(quán)限的處理、日志記錄和數(shù)據(jù)變化三個(gè)功能編寫代理類,在業(yè)務(wù)邏輯中根據(jù)具體需求改變代碼順序即可。
??缺點(diǎn):
??1)、代理類和委托類實(shí)現(xiàn)了相同的接口,代理類通過(guò)委托類實(shí)現(xiàn)了相同的方法。這樣就出現(xiàn)了大量的代碼重復(fù)。如果接口增加一個(gè)方法,除了所有實(shí)現(xiàn)類需要實(shí)現(xiàn)這個(gè)方法外,所有代理類也需要實(shí)現(xiàn)此方法。增加了代碼維護(hù)的復(fù)雜度。
??2)、代理對(duì)象只服務(wù)于一種類型的對(duì)象,如果要服務(wù)多類型的對(duì)象。勢(shì)必要為每一種對(duì)象都進(jìn)行代理,靜態(tài)代理在程序規(guī)模稍大時(shí)就無(wú)法勝任了。
動(dòng)態(tài)代理
??實(shí)現(xiàn)動(dòng)態(tài)代理的關(guān)鍵技術(shù)是反射。
??一般來(lái)說(shuō),對(duì)代理模式而言,一個(gè)主題類與一個(gè)代理類一一對(duì)應(yīng),這也是靜態(tài)代理模式的特點(diǎn)。
??但是,也存在這樣的情況,有n各主題類,但是代理類中的“前處理、后處理”都是一樣的,僅調(diào)用主題不同。也就是說(shuō),多個(gè)主題類對(duì)應(yīng)一個(gè)代理類,共享“前處理,后處理”功能,動(dòng)態(tài)調(diào)用所需主題,大大減小了程序規(guī)模,這就是動(dòng)態(tài)代理模式的特點(diǎn)。動(dòng)態(tài)代理主要有兩種:JDK自帶的動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理。
??首先是另一個(gè)靜態(tài)代理的實(shí)例:
1、一個(gè)可移動(dòng)接口
public interface Moveable {
public void move();
}
2、一個(gè)實(shí)現(xiàn)了該接口的Car類
public class Car implements Moveable {
@Override
public void move() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽車行駛中----");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3、現(xiàn)在需要有一個(gè)代理類來(lái)記錄Car的運(yùn)行時(shí)間:
public class CarTimeProxy implements Moveable {
private Moveable m;
public CarTimeProxy(Moveable m) {
super();
this.m = m;
}
@Override
public void move() {
long startTime = System.currentTimeMillis();
System.out.println("汽車行駛前----");
m.move();
long endTime = System.currentTimeMillis();
System.out.println("汽車行駛結(jié)束----行駛時(shí)間為:" + (endTime - startTime) + "毫秒!");
}
}
4、另一個(gè)代理類記錄Car的日志:
public class CarLogProxy implements Moveable {
private Moveable m;
public CarLogProxy(Moveable m) {
super();
this.m = m;
}
@Override
public void move() {
System.out.println("日志開始");
m.move();
System.out.println("日志結(jié)束");
}
}
5、客戶端的調(diào)用:
public class CarTest {
public static void main(String[] args) {
Car car = new Car();
// 先寫日志,再計(jì)時(shí)
CarTimeProxy ctp = new CarTimeProxy(car);
CarLogProxy clp = new CarLogProxy(ctp);
clp.move();
System.out.println();
// 先計(jì)時(shí),再寫日志
CarLogProxy clp1 = new CarLogProxy(car);
CarTimeProxy ctp1 = new CarTimeProxy(clp1);
ctp1.move();
}
}

JDK的動(dòng)態(tài)代理
在java的動(dòng)態(tài)代理機(jī)制中,有兩個(gè)重要的類或接口,一個(gè)是InvocationHandler(Interface)、另一個(gè)則是 Proxy(Class),這一個(gè)類和接口是實(shí)現(xiàn)我們動(dòng)態(tài)代理所必須用到的。


??JDK動(dòng)態(tài)代理的實(shí)現(xiàn)
??1、創(chuàng)建一個(gè)實(shí)現(xiàn)接口InvocationHandler的類,它必須實(shí)現(xiàn)invoke方法。
??使用JDK動(dòng)態(tài)代理類時(shí),需要實(shí)現(xiàn)InvocationHandler接口,所有動(dòng)態(tài)代理類的方法調(diào)用,都會(huì)交由InvocationHandler接口實(shí)現(xiàn)類里的invoke()方法去處理。這是動(dòng)態(tài)代理的關(guān)鍵所在。
??2、創(chuàng)建被代理的類以及接口。
??3、調(diào)用Proxy的靜態(tài)方法,創(chuàng)建代理類。
??newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h);
??4、通過(guò)代理調(diào)用方法。
??使用JDK動(dòng)態(tài)代理的方式實(shí)現(xiàn)上面Car的時(shí)間代理:
1、首先是InvocationHandler接口的實(shí)現(xiàn)類:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TimeHandler implements InvocationHandler {
// 被傳遞過(guò)來(lái)的要被代理的對(duì)象
private Object object;
public TimeHandler(Object object) {
super();
this.object = object;
}
/**
* proxy:被代理的對(duì)象
* method:被代理的方法
* args:被代理方法的參數(shù)
*
* 函數(shù)返回:method的返回
*
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startTime = System.currentTimeMillis();
System.out.println("汽車行駛前----");
method.invoke(object, args);
long endTime = System.currentTimeMillis();
System.out.println("汽車行駛結(jié)束----行駛時(shí)間為:" + (endTime - startTime) + "毫秒!");
return null;
}
}
2、創(chuàng)建動(dòng)態(tài)代理類:
/**
* @Description: JDK動(dòng)態(tài)代理的測(cè)試類
* @author: zxt
* @time: 2019年3月1日 下午7:59:29
*/
public class TimeHandlerTest {
public static void main(String[] args) {
// 需要被代理的對(duì)象
Car car = new Car();
InvocationHandler h = new TimeHandler(car);
Class<?> clazz = car.getClass();
/**
* 參數(shù)一:類加載器
* 參數(shù)二:被代理類實(shí)現(xiàn)的接口
* 參數(shù)三:InvocationHandler實(shí)例
*
* 函數(shù)返回:返回由InvocationHandler接口接收的被代理類的一個(gè)動(dòng)態(tài)代理類對(duì)象
*/
Moveable m = (Moveable) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), h);
m.move();
}
}
cglib動(dòng)態(tài)代理
??JDK動(dòng)態(tài)代理可以在運(yùn)行時(shí)動(dòng)態(tài)生成字節(jié)碼,主要使用到了一個(gè)接口InvocationHandler與Proxy.newProxyInstance靜態(tài)方法。使用內(nèi)置的Proxy實(shí)現(xiàn)動(dòng)態(tài)代理有一個(gè)問(wèn)題:被代理的類必須要實(shí)現(xiàn)某接口,未實(shí)現(xiàn)接口則沒辦法完成動(dòng)態(tài)代理。
??如果項(xiàng)目中有些類沒有實(shí)現(xiàn)接口,則不應(yīng)該為了實(shí)現(xiàn)動(dòng)態(tài)代理而刻意去抽象出一些沒有實(shí)際意義的接口,通過(guò)cglib可以解決該問(wèn)題。
??CGLIB(Code Generation Library)是一個(gè)開源項(xiàng)目,是一個(gè)強(qiáng)大的,高性能,高質(zhì)量的Code生成類庫(kù),它可以在運(yùn)行期擴(kuò)展Java類與實(shí)現(xiàn)Java接口,通俗地說(shuō)cglib可以在運(yùn)行時(shí)動(dòng)態(tài)生成字節(jié)碼。
??使用cglib完成動(dòng)態(tài)代理,大概的原理是:cglib繼承被代理的類,重寫方法,織入通知,動(dòng)態(tài)生成字節(jié)碼并運(yùn)行。對(duì)指定目標(biāo)類產(chǎn)生一個(gè)子類,通過(guò)方法攔截技術(shù)攔截所有父類的方法調(diào)用,因?yàn)槭抢^承實(shí)現(xiàn)所以final類是沒有辦法動(dòng)態(tài)代理的。
CGLIB動(dòng)態(tài)代理實(shí)例:
import java.util.Random;
// 不實(shí)現(xiàn)接口的被代理類
public class Train {
public void move() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("火車行駛中----");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
// 得到代理類的方法
public Object getProxy(Class<?> clazz) {
// 設(shè)置創(chuàng)建子類的類 (即我們需要為哪個(gè)類產(chǎn)生代理類)
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
/**
* 攔截所有目標(biāo)類方法的調(diào)用
*
* object:目標(biāo)類的實(shí)例
* method:目標(biāo)類的目標(biāo)方法的反射實(shí)例
* args:目標(biāo)方法的參數(shù)
* proxy:代理類的實(shí)例
*/
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
long startTime = System.currentTimeMillis();
System.out.println("火車行駛前----");
// 代理類調(diào)用父類的方法 (由于Cglib動(dòng)態(tài)代理的實(shí)現(xiàn)是通過(guò)繼承被代理類,因此代理類這里需要調(diào)用父類的方法)
proxy.invokeSuper(object, args);
long endTime = System.currentTimeMillis();
System.out.println("火車行駛結(jié)束----行駛時(shí)間為:" + (endTime - startTime) + "毫秒!");
return null;
}
}
public class CglibProxyTest {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
Train train = (Train) cglibProxy.getProxy(Train.class);
train.move();
}
}
JDK動(dòng)態(tài)代理的模擬實(shí)現(xiàn)
模擬JDK動(dòng)態(tài)代理的實(shí)現(xiàn),根據(jù)Java源代碼動(dòng)態(tài)生成代理類。
package com.zxt.jdkproxy;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import org.apache.commons.io.FileUtils;
import com.zxt.staticproxy.Car;
/**
*
* @Description: 模擬JDK動(dòng)態(tài)代理的實(shí)現(xiàn)
* 動(dòng)態(tài)代理的實(shí)現(xiàn)思路:
* 實(shí)現(xiàn)功能:通過(guò)自定義的Proxy的newProxyInstance方法返回代理對(duì)象
* 1、聲明一段源碼(動(dòng)態(tài)產(chǎn)生代理)
* 2、編譯源碼(JDK Compiler API),產(chǎn)生新的類(代理類)
* 3、將這個(gè)類load到內(nèi)存當(dāng)中,產(chǎn)生一個(gè)新的對(duì)象(代理對(duì)象)
* 4、return 代理對(duì)象
*
* @author: zxt
*
* @time: 2019年4月18日 下午3:44:58
*
*/
public class MyProxy {
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Object newProxyInstance(Class<?> inteface) throws Exception {
// 1、聲明一段源碼(動(dòng)態(tài)產(chǎn)生代理)
String rt = "\r\n";
String methodStr = "";
for(Method m : inteface.getMethods()) {
methodStr += " @Override" + rt
+ " public void " + m.getName() + "() {" + rt
+ " System.out.println(\"日志開始\");" + rt
+ " m." + m.getName() + "();" + rt
+ " System.out.println(\"日志結(jié)束\");" + rt
+ " }";
}
String code =
"package com.zxt.jdkproxy;" + rt + "\n"
+ "import com.zxt.staticproxy.Moveable;" + rt + "\n"
+ "public class $MyProxy0 implements " + inteface.getSimpleName() + " {" + rt + "\n"
+ " private " + inteface.getSimpleName() + " m;" + rt + "\n"
+ " public $MyProxy0(" + inteface.getSimpleName() + " m) {" + rt
+ " super();" + rt
+ " this.m = m;" + rt
+ " }" + rt + "\n"
+ methodStr + rt + "\n"
+ "}";
// 由源代碼生成java類文件
String filename = System.getProperty("user.dir") + "/bin/com/zxt/jdkproxy/$MyProxy0.java";
File file = new File(filename);
// 使用commons-io里面的簡(jiǎn)便的工具類來(lái)寫文件
FileUtils.writeStringToFile(file, code, "UTF-8");
// 2、編譯源碼(JDK Compiler API),產(chǎn)生新的類(代理類)
// 拿到編譯器
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// 文件管理者
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
// 獲取文件
Iterable units = fileManager.getJavaFileObjects(filename);
// 獲取編譯任務(wù)
CompilationTask task = compiler.getTask(null, fileManager, null, null, null, units);
// 編譯
task.call();
fileManager.close();
// 3、加載到內(nèi)存
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class c = cl.loadClass("com.zxt.jdkproxy.$MyProxy0");
// 4、返回代理類
Constructor ctr = c.getConstructor(inteface);
return ctr.newInstance(new Car());
}
public static void main(String[] args) {
}
}
public class MyProxyTest {
public static void main(String[] args) throws Exception {
Moveable m = (Moveable) MyProxy.newProxyInstance(Moveable.class);
m.move();
}
}
??可以發(fā)現(xiàn)上述實(shí)現(xiàn)中的源代碼是寫死在類中的,因此無(wú)法對(duì)任意類進(jìn)行動(dòng)態(tài)代理,所以仿照InvocationHandler接口,定義自己的InvocationHandler接口從而實(shí)現(xiàn)對(duì)不同的類進(jìn)行動(dòng)態(tài)代理。
import java.lang.reflect.Method;
public interface MyInvocationHandler {
public void invoke(Object o, Method m);
}
實(shí)現(xiàn)該接口的類
import java.lang.reflect.Method;
public class MyLogHandler implements MyInvocationHandler {
// 需要被代理的對(duì)象
private Object target;
public MyLogHandler(Object target) {
super();
this.target = target;
}
@Override
public void invoke(Object o, Method m) {
try {
System.out.println("日志開始");
m.invoke(target);
System.out.println("日志結(jié)束");
} catch (Exception e) {
e.printStackTrace();
}
}
}
對(duì)動(dòng)態(tài)代理MyProxy類進(jìn)行改進(jìn)
/**
*
* @Description: 模擬JDK動(dòng)態(tài)代理的實(shí)現(xiàn)
* 動(dòng)態(tài)代理的實(shí)現(xiàn)思路:
* 實(shí)現(xiàn)功能:通過(guò)自定義的Proxy的newProxyInstance方法返回代理對(duì)象
* 1、聲明一段源碼(動(dòng)態(tài)產(chǎn)生代理)
* 2、編譯源碼(JDK Compiler API),產(chǎn)生新的類(代理類)
* 3、將這個(gè)類load到內(nèi)存當(dāng)中,產(chǎn)生一個(gè)新的對(duì)象(代理對(duì)象)
* 4、return 代理對(duì)象
*
* @author: zxt
*
* @time: 2019年4月18日 下午3:44:58
*
*/
public class MyProxy {
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Object newProxyInstance(Class<?> inteface, MyInvocationHandler h) throws Exception {
// 1、聲明一段源碼(動(dòng)態(tài)產(chǎn)生代理)
String rt = "\r\n";
String methodStr = "";
for(Method m : inteface.getMethods()) {
methodStr += " @Override" + rt
+ " public void " + m.getName() + "() {" + rt
+ " try { " + rt
+ " Method md = " + inteface.getSimpleName() + ".class.getMethod(\""
+ m.getName() + "\");" + rt
+ " h.invoke(this, md);" + rt
+ " } catch (Exception e) { " + rt
+ " e.printStackTrace();" + rt
+ " }" + rt
+ " }";
}
String code =
"package com.zxt.jdkproxy;" + rt + "\n"
+ "import java.lang.reflect.Method;" + rt
+ "import com.zxt.staticproxy.Moveable;" + rt + "\n"
+ "public class $MyProxy0 implements " + inteface.getSimpleName() + " {" + rt + "\n"
+ " private MyInvocationHandler h;" + rt + "\n"
+ " public $MyProxy0( MyInvocationHandler h ) {" + rt
+ " this.h = h;" + rt
+ " }" + rt + "\n"
+ methodStr + rt + "\n"
+ "}";
// 由源代碼生成java類文件
String filename = System.getProperty("user.dir") + "/bin/com/zxt/jdkproxy/$MyProxy0.java";
File file = new File(filename);
// 使用commons-io里面的簡(jiǎn)便的工具類來(lái)寫文件
FileUtils.writeStringToFile(file, code, "UTF-8");
// 2、編譯源碼(JDK Compiler API),產(chǎn)生新的類(代理類)
// 拿到編譯器
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// 文件管理者
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
// 獲取文件
Iterable units = fileManager.getJavaFileObjects(filename);
// 獲取編譯任務(wù)
CompilationTask task = compiler.getTask(null, fileManager, null, null, null, units);
// 編譯
task.call();
fileManager.close();
// 3、加載到內(nèi)存
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class c = cl.loadClass("com.zxt.jdkproxy.$MyProxy0");
// 4、返回代理類
Constructor ctr = c.getConstructor(MyInvocationHandler.class);
return ctr.newInstance(h);
}
}
測(cè)試類:
public class MyProxyTest {
public static void main(String[] args) throws Exception {
// 需要被代理的對(duì)象
Car car = new Car();
MyInvocationHandler h = new MyLogHandler(car);
Moveable m = (Moveable) MyProxy.newProxyInstance(Moveable.class, h);
m.move();
}
}