动态代理类原理(示例代码参见java反射机制剖析(三)

a)  理解上面的动态代理示例流程

a)  理解上面的动态代理示例流程

b)  代理接口实现类源代码剖析

咱们一起来剖析一下代理实现类($Proxy0)的源代码和整个动态代理的流程。

$Proxy0生成的代码如下:

    import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy0 extends Proxy implements Manager { private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2; static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals",
new Class[] { Class.forName("java.lang.Object") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode",
new Class[0]);
m3 = Class.forName("com.ml.test.Manager").getMethod("test",
new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString",
new Class[0]);
} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
} catch (ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
} public $Proxy0(InvocationHandler invocationhandler) {
super(invocationhandler);
} @Override
public final boolean equals(Object obj) {
try {
return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))
.booleanValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
} @Override
public final int hashCode() {
try {
return ((Integer) super.h.invoke(this, m0, null)).intValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
} public final void test() {
try {
super.h.invoke(this, m3, null);
return;
} catch (Error e) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
} @Override
public final String toString() {
try {
return (String) super.h.invoke(this, m2, null);
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}

引入眼帘的是这个代理接口实现类实现了业务类的接口(也就是例子中的UserManager接口),又继承了基类Proxy类;

接着就是构造函数,在构造方法中把BusinessHandler传过去,接着$Proxy0调用父类Proxy的构造器,为h赋值(这里要看Proxy的构造方法);

随 后看到的就是这个类重写了Proxy类的Equals、hashCode、toString方法,又实现了业务类接口的方法(即UserManager的 test方法),具体重写和实现都是用到的super.h.invoke(即Proxy.h.invoke)这个方法。

简单分析完这个代理接口实现类,咱们下面来整体看一下这个动态代理是怎么实现的:

首先客户端初始化了BusinessHandler类,调用这个类的newProxyInstance(new UserManagerImpl())方法来初始化了上面的代理接口实现类;

接下来代理接口实现类通过构造函数把BusinessHandler传过去(也就是代码中的this),并通过Proxy的构造函数给h赋值;

随 后再客户端就能实例化出代理接口实现类$Proxy0,我们把它强制转换为业务实现接口(UserManager)类型的(为什么要强制转换,这里非常有 意思,如果不强制转换就会报错,这里很好解释,因为当前的环境根本不会知道这个代理接口实现类$Proxy0既继承Proxy又实现业务实现接口 UserManager,但是强制转换成UserManager它是可以做到的,因为当前环境中就有UserManager。这就是反射的厉害之处,可以 在运行时动态调用任何一个类并可以使用这个类的具体细节。);

之后当我们调用test方法的时候其实是调用了$Proxy0中的test方法,这个方法的实现是通过Proxy.h的invoke方法实现的(即调用了BusinessHandler.invoke方法);

之后在调用了Method的invoke方法(这时的参数是this,和args)。

这样就调用了UserManagerImpl的对应方法,之后返回给客户端。

到此就完成了整个的调用关系。

反射,反射,程序员的快乐

通 过上篇文章对动态代理进行了深度剖析,现在想起来还感觉非常有意思,这里面其实最根本的机制就是反射机制,运行时动态实例化任何一个类,并且调用它的具体 细节。现在反看动态代理的示例,其实发现这里最关键的还是在就在Proxy.newProxyInstance(..)方法执行时生成了$Proxy0的 内存字节码这一点上,当我们有了内存字节码,我们的反射就会大显威力,这样才有了我们之后的一系列的调用关系。

通过反射机制的分析和动态代理示例的剖析,发现编程是一件多么有意思的事情,以至于我们沉浸其中不能自拔。

最后总结一下:反射,反射,程序员的快乐!

心得:动态代理生成$Proxy0这个类,说明了用到"反射"这一知识点。

Java反射机制剖析(四)-深度剖析动态代理原理及总结的更多相关文章

  1. Java反射机制(四):动态代理

    一.静态代理 在开始去学习反射实现的动态代理前,我们先需要了解代理设计模式,那何为代理呢? 代理模式: 为其他对象提供一种代理,以控制对这个对象的访问. 先看一张代理模式的结构图: 简单的理解代理设计 ...

  2. JAVA反射机制--静态加载与动态加载

    Java反射是Java被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如pu ...

  3. Java Proxy和CGLIB动态代理原理

    动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译时就确定了,而动态代理的代理关 ...

  4. 动态代理:JDK原生动态代理(Java Proxy)和CGLIB动态代理原理+附静态态代理

    本文只是对原文的梳理总结,以及自行理解.自己总结的比较简单,而且不深入,不如直接看原文.不过自己梳理一遍更有助于理解. 详细可参考原文:http://www.cnblogs.com/Carpenter ...

  5. Java反射机制深度剖析

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! Java反射机制是Java语言中一种很重要的机制,可能在工作中用到的机会不多,但是在很多框架中都有用到这种机制.我们知道Java是一门静态 ...

  6. 文末送书四本 | 这篇Java反射机制太经典!不看后悔!

    先看再点赞,给自己一点思考的时间,如果对自己有帮助,微信搜索[程序职场]关注这个执着的职场程序员. 价值:Java技能,面试经验指导,简历优化,职场规划指导,技能提升方法,讲不完的职场故事,个人成长经 ...

  7. 【java基础】Java反射机制

    一.预先需要掌握的知识(java虚拟机)  1)java虚拟机的方法区:  java虚拟机有一个运行时数据区,这个数据区又被分为方法区,堆区和栈区,我们这里需要了解的主要是方法区.方法区的主要作用是存 ...

  8. 读懂框架设计的灵魂—Java反射机制

    尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 CS-Wiki(Gitee 官 ...

  9. 基础篇:深入解析JAVA反射机制

    目录 反射的概念 获取Class的三种方法 JAVA反射API 反射机制应用的场景 反射和JDK动态代理 欢迎指正文中错误 关注公众号,一起交流 参考文章 反射的概念 java的放射机制:在程序运行时 ...

随机推荐

  1. UIDatePicker的使用

    UIDatePicker的介绍 UIDatePicker这个类的对象让用户可以在多个车轮上选择日期和时间.iPhone手机上的‘时钟’应用程序中的时间与闹铃中便使用了该控件.使用这个控件时,如果你能配 ...

  2. 一些IO流的知识

    IO流: 输入流:输出流: 字节流:字符流:为了处理文字数据方便而出现的对象. 其实这些对象的内部使用的还是字节流(因为文字最终也是字节数据) 只不过,通过字节流读取了相对应的字节数,没有对这些字节直 ...

  3. php基础知识(二)---2017-04-14

    1.字符串的三种表达形式: (1)双引号 (2)单引号 (3)尖括号 $s = <<<A <div style="width:500px; height:100px; ...

  4. Win10隐藏硬盘分区

    前几天装了Win10和OpenSUSE的双系统,结果挂载Linux的分区被Windows识别成了三个盘符,在Windows下是不能直接访问它们的,而且双击还会提示你是否格式化. 因为在windows放 ...

  5. 《深入理解Java函数式编程》系列文章

    Introduction 本系列文将帮助你理解Java函数式编程的用法.原理. 本文受启发于JavaOne 2016关于Lambda表达式的相关主题演讲Lambdas and Functional P ...

  6. 浅谈C#数组(二)

    六.枚举集合 在foreach语句中使用枚举,可以迭代集合中的元素,且无需知道集合中元素的个数.foreach语句使用一个枚举器.foreach会调用实现了IEnumerable接口的集合类中的Get ...

  7. OpenCV 玩九宫格数独(二):knn 数字识别

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:刘潇龙 前言 首先需要说明,这里所说的数字识别不是手写数字识别! 但凡对机器学习有所了解的人,相信看到数 ...

  8. Linux-进程描述(5)之进程环境

    main函数和启动例程 当内核使用一个exec函数执行C程序时,在调用main函数之前先调用一个特殊的启动例程,可执行程序将此例程指定为程序的起始地址.启动例程从内核获取命令行参数和环境变量,然后为调 ...

  9. apache配置多个虚拟目录站点

    错误的做法 网上查了几个资料,做法如下:比如想配置两个www.web1.com  www.web2.com站点 打开httpd.conf ,然后添加: <VirtualHost *:80> ...

  10. JavaScript中undefined 和not defined

    首先呢,我们来介绍undefined,xx is not defined的区别 (创建一个html文件,在头部编写JavaScript代码) 我们先编写如下代码: <script type=&q ...