jdk動態代理要對一個類進行代理,被代理的類必須實現至少一個接口,并且只有接口中的方法才能被代理。
jdk實現動態代理一般分為三步:
1. 編寫接口和實現類。
2. 寫一個處理器,該處理器實現InvocationHandler接口,該接口只有一個方法,其簽名為public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;可在該處理器的實現方法中,在方法調用前和調用后加入自己的代碼,從而進行動態攔截。要注意的是proxy為生成的動態代理類,并不是真的我們被代理的類,所以可在處理器中加入Object類型的成員變量,指向我們真正要求被代理的類(即第1步中的實現類)。
3. 使用java.lang.reflect.Proxy類的newProxyInstance方法生成動態代理類。對所有要代理方法的調用,都是直接調用生成的動態代理類的方法即可,但是要先對它進行強制類型轉換,轉換成我們要調用的方法的接口。
JDK原理分析:
通過分析Proxy的源代碼,可看到動態代理類的詳細生成。newProxyInstance方法首先生成動態代理類的Class實例,再調用它的參數類型為InvocationHandler的構造函數來生成動態代理類并返回。
動態代理類的Class實例是怎么生成的呢,是通過ProxyGenerator類來生成動態代理類的class字節流,把它載入方法區。
分析class字節流生成的過程可以看到它使用Proxy為它的父類,實現所有要代理的接口的方法,每個方法的實現體里主要都是調用處理器的invoke方法。
class字節流的生成過程的主要代碼如下:
}
List list;
for(Iterator iterator = proxyMethods.values().iterator(); iterator.hasNext(); checkReturnTypes(list))
list = (List)iterator.next();
try
{
methods.add(generateConstructor());
for(Iterator iterator1 = proxyMethods.values().iterator(); iterator1.hasNext();)
{
List list1 = (List)iterator1.next();
Iterator iterator2 = list1.iterator();
while(iterator2.hasNext())
{
ProxyMethod proxymethod = (ProxyMethod)iterator2.next();
fields.add(new FieldInfo(proxymethod.methodFieldName, "Ljava/lang/reflect/Method;", 10));
methods.add(<SPAN style="COLOR: red">proxymethod.generateMethod()</SPAN><SPAN style="COLOR: #000000">);</SPAN>
fieldinfo = (FieldInfo)iterator3.next();
//添加方法
dataoutputstream.writeShort(methods.size());
MethodInfo methodinfo;
for(Iterator iterator4 = methods.iterator(); iterator4.hasNext(); methodinfo.write(dataoutputstream))
methodinfo = (MethodInfo)iterator4.next();
dataoutputstream.writeShort(0);
}
catch(IOException ioexception1)
{
throw new InternalError("unexpected I/O Exception");
}
return bytearrayoutputstream.toByteArray();
}
新聞熱點
疑難解答