一、動(dòng)態(tài)代理類
1茉唉、Java的動(dòng)態(tài)代理類位于java.lang.reflect包下。一般主要涉及到下面兩個(gè)類:
(1) Interface InvocationHandler。該接口只定義了一個(gè)方法
/**
* @param proxy 該方法被調(diào)用的代理實(shí)例
* @param method 被代理對(duì)象想要執(zhí)行的方法
* @param args 所執(zhí)行方法的參數(shù)
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
(2) Proxy颠印。該類為動(dòng)態(tài)代理類纲岭,作用相當(dāng)于靜態(tài)代理中的ProxySubject。主要有下面三個(gè)方法:
//構(gòu)造函數(shù)线罕,用于給內(nèi)部的h賦值止潮。
protected Proxy(InvocationHandler h)
//獲得一個(gè)代理類,其中l(wèi)oader是類裝載器钞楼,interfaces是真實(shí)類所擁有的全部接口的數(shù)組
static Class getProxyClass (ClassLoader loader, Class[] interfaces)
//返回代理類的一個(gè)實(shí)例喇闸,返回后的代理類可以當(dāng)作被代理類使用(可使用被代理類的在Subject接口中聲明過的方法
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
2、Dynamic Proxy是在運(yùn)行時(shí)生成的class询件,生成它時(shí)必須提供一組接口燃乍,然后它就宣稱實(shí)現(xiàn)了這些接口,因此可以把它當(dāng)做這些接口中的任意一個(gè)來用宛琅。實(shí)際上刻蟹,這個(gè)Dynamic Proxy就是一個(gè)Proxy,它并不會(huì)完成實(shí)質(zhì)的工作嘿辟,在生成它的實(shí)例時(shí)必須提供一個(gè)InvocationHandler實(shí)例舆瘪,由它來完成實(shí)際的工作。
二红伦、demo說明
- 各個(gè)文件介紹
//Subject.java //抽象角色
//RealSubject.java //真實(shí)角色
//DynamicSubject.java //代理角色
//Client.java //客戶端
1英古、 Subject.java
public interface Subject
{
public void request();
}
2、RealSubject.java
public class RealSubject implements Subject
{
@Override
public void request()
{
System.out.println("From real Subject!");
}
}
3昙读、DynamicSubject.java
/**
* 動(dòng)態(tài)代理類
* 動(dòng)態(tài)代理類必須實(shí)現(xiàn)InvocationHandler接口
*該代理類內(nèi)部屬性是Object對(duì)象召调,實(shí)際使用時(shí)通過構(gòu)造方法傳進(jìn)一個(gè)來一個(gè)對(duì)象
*此外,該代理類還實(shí)現(xiàn)了invoke方法蛮浑,該方法中的method.invoke就是執(zhí)行
*被代理對(duì)象想要執(zhí)行的方法唠叛,方法參數(shù)是sub,表示該方法從屬于sub陵吸。同時(shí)我們
*還可以在執(zhí)行真實(shí)對(duì)象的方法前后添加一些額外的方法玻墅。
* @author Chuan
*
*/
public class DynamicSubject implements InvocationHandler
{
private Object sub;
public DynamicSubject(Object object)
{
this.sub = object;
}
/**
* @param proxy 該方法被調(diào)用的代理實(shí)例
* @param method 被代理對(duì)象想要執(zhí)行的方法
* @param args 所執(zhí)行方法的參數(shù)
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
System.out.println("before calling: " + method);
method.invoke(sub, args);
System.out.println("after calling: " + method);
return null;
}
}
4、Client.java
public class Client
{
public static void main(String[] args)
{
RealSubject realSubject = new RealSubject();
InvocationHandler handler = new DynamicSubject(realSubject);
/**
*Proxy.newProxyInstance()一次性生成代理類
* Proxy.newProxyInstance()方法的第一個(gè)參數(shù)是代理類的裝載器
* 第二個(gè)參數(shù)是代理類應(yīng)該實(shí)現(xiàn)的接口壮虫,即被代理類實(shí)現(xiàn)的接口
* 第三個(gè)參數(shù) 是一個(gè)InvocationHandler
*
* 最后在執(zhí)行過程中動(dòng)態(tài)生成一個(gè)$Proxy0對(duì)象澳厢,
* $Proxy0類實(shí)現(xiàn)了Subject接口(realSubject.getClass().getInterfaces())
*/
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(), handler);
//代理對(duì)象調(diào)用方法,實(shí)際上是轉(zhuǎn)到動(dòng)態(tài)代理中的invoke方法囚似,并執(zhí)行
subject.request();
System.out.println(subject.getClass());
}
}
3剩拢、動(dòng)態(tài)代理的步驟
(1)、創(chuàng)建一個(gè)實(shí)現(xiàn)了InvocationHandler接口的類饶唤,它必須實(shí)現(xiàn)invoke方法徐伐;
(2)、創(chuàng)建被代理的類以及接口募狂;
(3)办素、通過Proxy的靜態(tài)方法newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)創(chuàng)建一個(gè)代理角雷;
(4)、 通過代理調(diào)用方法性穿。