手机
当前位置:查字典教程网 >编程开发 >Java >java jdk动态代理详解
java jdk动态代理详解
摘要:jdk动态代理要对一个类进行代理,被代理的类必须实现至少一个接口,并且只有接口中的方法才能被代理。jdk实现动态代理一般分为三步:1.编写接...

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字节流的生成过程的主要代码如下:

复制代码 代码如下:

private byte[] generateClassFile()

{

addProxyMethod(hashCodeMethod, java/lang/Object);

addProxyMethod(equalsMethod, java/lang/Object);

addProxyMethod(toStringMethod, java/lang/Object);

for(int i = 0; i < interfaces.length; i++)

{

Method amethod[] = interfaces[i].getMethods();

for(int k = 0; k < amethod.length; k++)

addProxyMethod(amethod[k], interfaces[i]);

}

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>proxymethod.generateMethod()</SPAN><SPAN>);</SPAN>

复制代码 代码如下:

}

}

methods.add(generateStaticInitializer());

}

catch(IOException ioexception)

{

throw new InternalError("unexpected I/O Exception");

}

if(methods.size() > 65535)

throw new IllegalArgumentException("method limit exceeded");

if(fields.size() > 65535)

throw new IllegalArgumentException("field limit exceeded");

cp.getClass(dotToSlash(className));

cp.getClass("java/lang/reflect/Proxy");

for(int j = 0; j < interfaces.length; j++)

cp.getClass(dotToSlash(interfaces[j].getName()));

cp.setReadOnly();

ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();

DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream);

try

{

dataoutputstream.writeInt(-889275714);

dataoutputstream.writeShort(0);

dataoutputstream.writeShort(49);

cp.write(dataoutputstream);

dataoutputstream.writeShort(49);

dataoutputstream.writeShort(cp.getClass(dotToSlash(className)));

dataoutputstream.writeShort(cp.getClass("java/lang/reflect/Proxy"));

dataoutputstream.writeShort(interfaces.length);

for(int l = 0; l < interfaces.length; l++)

dataoutputstream.writeShort(cp.getClass(dotToSlash(interfaces[l].getName())));

dataoutputstream.writeShort(fields.size());

FieldInfo fieldinfo;

复制代码 代码如下:

//添加属性

for(Iterator iterator3 = fields.iterator(); iterator3.hasNext(); fieldinfo.write(dataoutputstream))

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();

}

注:代码中加红部分proxymethod.generateMethod()为每个方法生成方法体,通过查看源码可以看出都是在调用InvocationHandler接口的实现处理器的invoke方法。

【java jdk动态代理详解】相关文章:

java 图片加水印实例代码

java加密枝术深入理解

java 自动生成略缩图示例代码

Java事务的个人理解小结

深入Java不可变类型的详解

java集合框架的体系结构详细说明

代理角色java设计模式之静态代理详细介绍

java 递归深入理解

Java动态代理的应用详解

深入java内存查看与分析详解

精品推荐
分类导航