动态代理的简单实例.
在上一篇文章《設(shè)計(jì)模式:Java的代理模式》中講解了代理模式的靜態(tài)代理方法。比靜態(tài)代理更靈活的就是動(dòng)態(tài)代理了。
Java動(dòng)態(tài)代理類位于java.lang.reflect包下,一般主要涉及到以下兩個(gè)類:
?(1)Interface InvocationHandler:該接口中僅定義了一個(gè)方法
public object invoke(Object obj,Method method, Object[] args)
在實(shí)際使用時(shí),第一個(gè)參數(shù)obj一般是指代理類,method是被代理的方法,如前文中的request(),args為該方法的參數(shù)數(shù)組。 這個(gè)抽象方法在代理類中動(dòng)態(tài)實(shí)現(xiàn)。
(2)Proxy:該類即為動(dòng)態(tài)代理類,作用類似于前文中的ProxySubject,其中主要包含以下內(nèi)容:
a)protected Proxy(InvocationHandler h):構(gòu)造函數(shù),用于給內(nèi)部的h賦值。
b)static Class getProxyClass (ClassLoader loader, Class[] interfaces):獲得一個(gè)代理類,其中l(wèi)oader是類裝載器,interfaces是真實(shí)類所擁有的全部接口的數(shù)組。
c)static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理類的一個(gè)實(shí)例,返回后的代理類可以當(dāng)作被代理類使用(可使用被代理類的在Subject接口中聲明過的方法)
?
所謂Dynamic Proxy是這樣一種class:它是在運(yùn)行時(shí)生成的class,在生成它時(shí)你必須提供一組interface給它,然后該class就宣稱它實(shí)現(xiàn)了這些 interface。你當(dāng)然可以把該class的實(shí)例當(dāng)作這些interface中的任何一個(gè)來用。當(dāng)然,這個(gè)Dynamic Proxy其實(shí)就是一個(gè)Proxy,它不會替你作實(shí)質(zhì)性的工作,在生成它的實(shí)例時(shí)你必須提供一個(gè)handler,由它接管實(shí)際的工作。在使用動(dòng)態(tài)代理類時(shí),我們必須實(shí)現(xiàn)InvocationHandler接口
實(shí)例:
一個(gè)接口類Subject:
public interface Subject{
public void request();
}
實(shí)現(xiàn)Subject接口的實(shí)體類RealSubject:
public class RealSubject implements Subject{
public void request()
{
System.out.println("From real subject!");
}
}
動(dòng)態(tài)代理類DynamicSubject:
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;
/**
* 該代理類的內(nèi)部屬性是Object類型,實(shí)際使用的時(shí)候通過該類的構(gòu)造方法傳遞進(jìn)來一個(gè)對象
* 此外,該類還實(shí)現(xiàn)了invoke方法,該方法中的method.invoke其實(shí)就是調(diào)用被代理對象的將要
* 執(zhí)行的方法,方法參數(shù)是sub,表示該方法從屬于sub,通過動(dòng)態(tài)代理類,我們可以在執(zhí)行真實(shí)對象的方法前后
* 加入自己的一些額外方法。
*
*/
public class DynamicSubject implements InvocationHandler
{
private Object sub;
public DynamicSubject(Object obj)
{
this.sub = obj;
}
//當(dāng)外界調(diào)用代理類實(shí)現(xiàn)的接口方法時(shí),將自動(dòng)調(diào)用此invoke()方法.method參數(shù)為外界欲調(diào)用的方法(由Proxy生成).
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
System.out.println("before calling: " + method);
//反射調(diào)用方法,sub是傳入的實(shí)體對象,method為外界欲調(diào)用的方法.代理功能實(shí)現(xiàn)!
method.invoke(sub, args);
System.out.println(args == null);
System.out.println("after calling: " + method);
return null;
}
}
使用動(dòng)態(tài)代理Client:
import java.lang.reflect.Proxy;
public class Client
{
public static void main(String[] args)
{
RealSubject realSubject = new RealSubject();
InvocationHandler handler = new DynamicSubject(realSubject);
Class<?> classType = handler.getClass();
// 下面的代碼一次性生成代理
//newProxyInstance創(chuàng)建的對象(假設(shè)名為:proxy)實(shí)現(xiàn)了實(shí)體類RealSubject的所有接口(參數(shù)2)
//然后就可以將proxy強(qiáng)制轉(zhuǎn)換為Subject類型.
Subject subject = (Subject) Proxy.newProxyInstance(classType
.getClassLoader(), realSubject.getClass().getInterfaces(),
handler);
//這里調(diào)用了request()方法,實(shí)際上就是調(diào)用proxy實(shí)現(xiàn)的接口的request()方法,該方法會調(diào)用DynamicSubject的invoke()方法.
//并傳入request()方法對的method對象(實(shí)際上是用反射)和方法參數(shù).
subject.request();
System.out.println(subject.getClass());
}
}
程序運(yùn)行結(jié)果:
before calling: public abstract void com.shengsiyuan.dynamicproxy.Subject.request()
From real subject!
true
after calling: public abstract void com.shengsiyuan.dynamicproxy.Subject.request()
class $Proxy0
?然后我們整合一下,將代理:
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Vector;
public class VectorProxy implements InvocationHandler
{
private Object proxyObj;
public VectorProxy(Object obj)
{
this.proxyObj = obj;
}
/*
* 該方法生成一個(gè)實(shí)現(xiàn)了Object的接口的對象
*/
public static Object factory(Object obj)
{
Class<?> classType = obj.getClass();
return Proxy.newProxyInstance(classType.getClassLoader(),
classType.getInterfaces(), new VectorProxy(obj));
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
//輸出參數(shù)
if(null != args)
{
for(Object obj : args)
{
System.out.println("參數(shù):"+obj);
}
}
Object object = method.invoke(proxyObj, args);
return object;
}
public static void main(String[] args)
{
//List是一個(gè)接口,Vector實(shí)現(xiàn)了List接口
List v = (List)factory(new Vector());
System.out.println(v.getClass().getName());
v.add("New");
v.add("York");
System.out.println(v);
v.remove(0);
System.out.println(v);
}
}
程序運(yùn)行結(jié)果是:
$Proxy0
參數(shù):New
參數(shù):York
[New, York]
參數(shù):0
[York]
總結(jié):
通過這種方式,被代理的對象(RealSubject)可以在運(yùn)行時(shí)動(dòng)態(tài)改變,需要控制的接口(Subject接口)可以在運(yùn)行時(shí)改變,控制的方式(DynamicSubject類)也可以動(dòng)態(tài)改變,從而實(shí)現(xiàn)了非常靈活的動(dòng)態(tài)代理關(guān)系。
本文為<北京圣思園Java培訓(xùn)教學(xué)視頻Java.SE>視頻筆記
轉(zhuǎn)載于:https://www.cnblogs.com/myfjd/archive/2012/01/14/2322480.html
總結(jié)
以上是生活随笔為你收集整理的动态代理的简单实例.的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 正式入驻51CTO
- 下一篇: 转载:使用 GNU Libtool 创建