栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java:Jdk动态代理技术解析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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."":(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后,后面就是实例化的操作!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/755697.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号