JDK动态代理案例与原理分析
一、JDK动态代理实现案例
Person接口
package com.zhoucong.proxy.jdk;
public interface Person {
// 寻找真爱
void findlove();
}
人物实现类
package com.zhoucong.proxy.jdk;
public class Zhangsan implements Person{
@Override
public void findlove() {
System.out.println("我叫张三,性别女,我找对象的要求如下:\n");
System.out.println("高富帅");
System.out.println("有房有车");
System.out.println("身高180cm以上,体重70kg");
}
}
代理类
package com.zhoucong.proxy.jdk; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class MeiPo implements InvocationHandler{ private Person target; // 获取被代理人的个人资料
public Object getInstance(Person target) throws Exception {
this.target = target;
Class clazz = target.getClass();
System.out.println("被代理对象的class是:"+ clazz);
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); } @Override
public Object invoke(Object arg0, Method method, Object[] args) throws Throwable {
System.out.println("我是媒婆!!");
System.out.println("开始信息海选...");
System.out.println("-------------"); method.invoke(this.target, args);
System.out.println("-------------");
System.out.println("如果合适的话,就准备办事");
return null;
} }
运行测试
package com.zhoucong.proxy.jdk;
public class TestFindLove { public static void main(String[] args) { try {
Person obj = (Person) new MeiPo().getInstance(new Zhangsan());
System.out.println(obj.getClass());
obj.findlove(); /**
* 原理:
* 1.拿到被代理对象的引用,然后获取它的接口
* 2.jdk代理重新生成一个类,同时实现我们个额的代理对象所实现的接口
* 3.把被代理对象的引用也拿到了
* 4.重新动态生成一个class字节码
* 5.然后编译
*/ } catch (Exception e) {
e.printStackTrace();
}
} }
运行结果:

重点:
代理前对象为 com.zhoucong.proxy.jdk.Zhangsan
代理后获得的对象 com.sun.proxy.$Proxy0
二、原理分析
获取$Proxy0.class字节码内容
package com.zhoucong.proxy.jdk; import java.io.FileOutputStream;
import sun.misc.ProxyGenerator; public class TestFindLove { public static void main(String[] args) { try {
Person obj = (Person) new MeiPo().getInstance(new Zhangsan());
System.out.println(obj.getClass());
obj.findlove(); // 获取字节码内容
// ProxyGenerator需要导入jdk安装目录jre/bin下的rt.jar byte[] generateProxyClass = ProxyGenerator.generateProxyClass("$Proxy0", new Class[] { Person.class });
// 输出到本地
FileOutputStream os = new FileOutputStream("E:/GP_WORKSPACE/$Proxy0.class");
os.write(generateProxyClass);
os.close(); } catch (Exception e) {
e.printStackTrace();
}
} }
利用反编译工具得到Java文件如下:
$Proxy0.java
import com.zhoucong.proxy.jdk.Person;
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 Person {
private static Method m1; private static Method m2; private static Method m0; private static Method m3; public $Proxy0(InvocationHandler paramInvocationHandler) {
super(paramInvocationHandler);
} public final boolean equals(Object paramObject) {
try {
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
} catch (Error|RuntimeException error) {
throw null;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
} public final String toString() {
try {
return (String)this.h.invoke(this, m2, null);
} catch (Error|RuntimeException error) {
throw null;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
} public final int hashCode() {
try {
return ((Integer)this.h.invoke(this, m0, null)).intValue();
} catch (Error|RuntimeException error) {
throw null;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
} public final void findlove() {
try {
this.h.invoke(this, m3, null);
return;
} catch (Error|RuntimeException error) {
throw null;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
} static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m3 = Class.forName("com.zhoucong.proxy.jdk.Person").getMethod("findlove", new Class[0]);
return;
} catch (NoSuchMethodException noSuchMethodException) {
throw new NoSuchMethodError(noSuchMethodException.getMessage());
} catch (ClassNotFoundException classNotFoundException) {
throw new NoClassDefFoundError(classNotFoundException.getMessage());
}
}
}
要点分析:
特点:1、JDK代理生成的类实现了Person接口继承父类Proxy
分析:JDK实现动态代理必须要有接口(cglib没有)
2、静态代码块获取了接口中的方法
m3 = Class.forName("com.zhoucong.proxy.jdk.Person").getMethod("findlove", new Class[0]);
3、JDK代理生成的类实现了接口方法,里面写了重要的一句话
this.h.invoke(this, m3, null);
分析:this.h 去父类Proxy中查看得知为父类的成员变量
/**
* the invocation handler for this proxy instance.
* @serial
*/
protected InvocationHandler h;
即MeiPo类并且调用了里面的Object invoke(Object arg0, Method method, Object[] args)方法
@Override
public Object invoke(Object arg0, Method method, Object[] args) throws Throwable {
System.out.println("我是媒婆!!");
System.out.println("开始信息海选...");
System.out.println("-------------");
// this.target.findlove(); //还可以写成如下,效果一样
// 利用反射机制实现
method.invoke(this.target, args);
System.out.println("-------------");
System.out.println("如果合适的话,就准备办事");
return null;
}
JDK动态代理案例与原理分析的更多相关文章
- (转)细说JDK动态代理的实现原理
原文:http://blog.csdn.net/mhmyqn/article/details/48474815 关于JDK的动态代理,最为人熟知的可能要数Spring AOP的实现,默认情况下,Spr ...
- JDK动态代理实现源码分析
JDK动态代理实现方式 在Spring框架中经典的AOP就是通过动态代理来实现的,Spring分别采用了JDK的动态代理和Cglib动态代理,本文就来分析一下JDK是如何实现动态代理的. 在分析源码之 ...
- JDK动态代理的实现原理
学习JDK动态代理,从源码层次来理解其实现原理参考:http://blog.csdn.net/jiankunking/article/details/52143504
- jdk动态代理使用及原理
jdk动态代理的使用 1.创建实现InvocationHandler接口的类,实现invoke(Object proxy, Method method, Object[] args)接口,其中invo ...
- Java JDK 动态代理实现和代码分析
JDK 动态代理 内容 一.动态代理解析 1. 代理模式 2. 为什么要使用动态代理 3. JDK 动态代理简单结构图 4. JDK 动态代理实现步骤 5. JDK 动态代理 API 5.1 java ...
- JDK 动态代理 源码简单分析
代理的作用就是在访问真实对象之前或者之后可以额外加入一些操作. JDK 的动态代理 只需要 5 步. 真实对象必须要实现接口,首先创建一个接口 public interface HelloWorld ...
- jdk动态代理 案例
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflec ...
- 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)
代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...
- 解析JDK动态代理实现原理
JDK动态代理使用实例 代理模式的类图如上.关于静态代理的示例网上有很多,在这里就不讲了. 因为本篇讲述要点是JDK动态代理的实现原理,直接从JDK动态代理实例开始. 首先是Subject接口类. p ...
随机推荐
- 团队作业4-Day5
团队作业4-Day5 项目git地址 1. 站立式会议 2. 项目燃尽图 3. 适当的项目截图 4. 代码/文档签入记录(部分) 5. 每人每日总结 吴梓华:补充了样式代码以方便调试. 白军强:顺利完 ...
- 百度前端技术学院-基础-day3
2020.9.15 第三天的课程内容,复习了一些CSS的基础属性(果然不用就会忘). 学习了一些新的属性,比如text-shadow.text-indent(还不是很清楚).font-style等等. ...
- UOJ61. 【UR #5】怎样更有力气
题目链接 Statement 给定一棵 \(n\) 点树 \(T\) 和 \(m\) 个操作 v u w : 在 \(T\) 中 \(u,v\) 的最短路上所有点里面选出若干对(可以不选,可以重复), ...
- DarkMode(1):产品应用深色模式分析
为什么Dark Mode变得越来越流行 2018 年的 macOS Mojave 率先支持了深色外观,紧接着 Windows 10 在 2018 年的 10 月份大版本更新中,也引入了 Dark Mo ...
- WindowsPhone8.1 开发-- 二维码扫描
随着 WinRT 8.1 API 的发布,Windows 8.1 和 Windows Phone 8.1 (基于 WinRT) 应用程序的开发模型经历了戏剧性的收敛性.与一些特定于平台的考虑,我们现在 ...
- 史上最全单链表的增删改查反转等操作汇总以及5种排序算法(C语言)
目录 1.准备工作 2.创建链表 3.打印链表 4.在元素后面插入元素 5.在元素前面增加元素 6.删除链表元素,要注意删除链表尾还是链表头 7.根据传入的数值查询链表 8.修改链表元素 9.求链表长 ...
- Unity GameObject
GameObject 游戏对象 GameObject是unity所有实体的基类 gameObject 获取当前脚本所挂载的游戏对象 一般来说,在属性视图中能看到或修改的属性,我们同样可以在脚本中获取并 ...
- Unity射击实例讲解—主角创建
前言: 经过三分钟的思考决定换个标题,这两天其实游戏制作进度推了大半了,加入了许多自我创作的素材,不过想一想用来讲解的实例不该这么花哨,决定还是参照我的一些教材做一些简单的示例不然要说的东西太多,本人 ...
- 302跳转导致的url劫持
介绍一个 网站监测工具:iis7网站监测IIS7网站监控工具可以做到提前预防各类网站劫持,并且是免费在线查询,适用于各大站长,政府网站,学校,公司,医院等网站.它可以做到24小时定时监控,同时它可 ...
- 安装nodejs 版本控制器
安装下载地址: https://pan.baidu.com/s/1Ed_IPDTOHxR9NShUEau-ZA 下载好后,放在安装nodejs的文件夹下 然后敲cmd,进入安装nodejs的文件夹下. ...