Java:Jdk动态代理技术解析
Posted 你是小KS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java:Jdk动态代理技术解析相关的知识,希望对你有一定的参考价值。
当前版本jdk1.8
1. 声明
当前内容主要为解析jdk的动态代理技术,当前内容参考jdk源码
2. 创建jdk方式解析
基本的jdk动态代理创建方法如下:
public static Object newProxyInstance(
ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
一般是需要被代理的接口和自定义的InvocationHandler,找到如下方法内容
从注释中可以得到信息,代理类是被生成出来的,然后动态加载到jvm中的,最后通过实例化操作返回给用户的
继续查看生成代理类的方法
其中限定了jdk代理的接口必须小于65535个
,且注释中表明是通过加载器方式且使用了缓存,但是实际创建代理类是使用ProxyClassFactory生成的
此时直接找到ProxyClassFactory这个类并找到其中的方法
可以发现实际上为ProxyGenerator方式生成的代理,此时继续找到ProxyGenerator类,并得到如下内容
这个是一个class文件的基本构造,且该class文件是生成的byte[],并且发现了如下特点
- 该代理类的超类就是Proxy
- 该代理类实际上本身就是实现了接口的类
3. 手动将查看生成的代理类的byte[]并解析
这里可以将ProxyGenerator的源码得到并实现byte[]生成且写出到文件中,这里使用一个简单的代理Demo
public interface Say
void say();
public static class Me implements Say
public void say()
System.out.println("say .........");
public static void main(String[] args) throws FileNotFoundException
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
Class<?>[] interfaces = Say.class ;
String proxyName = "com.hy.java.proxy.HY$Proxy";
byte[] generateProxyClass = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);
String outputPath = "C:\\\\Users\\\\admin\\\\Desktop\\\\a.class";
try (FileOutputStream fileOutputStream = new FileOutputStream(new File(outputPath)))
fileOutputStream.write(generateProxyClass, 0, generateProxyClass.length);
catch (IOException e) // TODO Auto-generated catch block
e.printStackTrace();
执行后并得到生成的文件a.class,接下来开始分析实际的字节码
执行命令:javap -verbose a.class
public final class com.hy.java.proxy.HY$Proxy extends java.lang.reflect.Proxy implements com.hy.java.proxy.factory.ProxyGeneratorTest$Say
所以默认生成的代理类是继承Proxy且实现了对应的接口的
查看构造函数,发现只有一个有参数的构造函数InvocationHandler并将其传递给Proxy中存放的h,所以实例化的时候是需要这个的,特别的发现了一个final的say方法被实现了
public final void say() throws ;
descriptor: ()V
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=10, locals=2, args_size=1
0: aload_0
1: getfield #16 // Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
4: aload_0
5: getstatic #57 // Field m3:Ljava/lang/reflect/Method;
8: aconst_null
9: invokeinterface #28, 4 // InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
14: pop
15: return
16: athrow
17: astore_1
18: new #42 // class java/lang/reflect/UndeclaredThrowableException
21: dup
22: aload_1
23: invokespecial #45 // Method java/lang/reflect/UndeclaredThrowableException."<init>":(Ljava/lang/Throwable;)V
26: athrow
Exception table:
from to target type
0 16 16 Class java/lang/Error
0 16 16 Class java/lang/RuntimeException
0 16 17 Class java/lang/Throwable
Exceptions:
解析后得到执行步骤:使用Proxy中的h(InvocationHandler)并完成I的调用操作
所以得到,被jdk动态代理的接口默认会被创建代理的实例所实现,且该接口的实现方式就是转发当前的方法调用操作,其中使用m3记录say这个方法
4. 图解和总结
jdk的动态代理其实就是class字节码动态生成并被jvm加载,实例化的操作,其所有的方法都会在其中实现并被转发给InvocationHandler
所以当类被加载并生成Class后,后面就是实例化的操作!
以上是关于Java:Jdk动态代理技术解析的主要内容,如果未能解决你的问题,请参考以下文章