一、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动态代理案例与原理分析的更多相关文章

  1. (转)细说JDK动态代理的实现原理

    原文:http://blog.csdn.net/mhmyqn/article/details/48474815 关于JDK的动态代理,最为人熟知的可能要数Spring AOP的实现,默认情况下,Spr ...

  2. JDK动态代理实现源码分析

    JDK动态代理实现方式 在Spring框架中经典的AOP就是通过动态代理来实现的,Spring分别采用了JDK的动态代理和Cglib动态代理,本文就来分析一下JDK是如何实现动态代理的. 在分析源码之 ...

  3. JDK动态代理的实现原理

    学习JDK动态代理,从源码层次来理解其实现原理参考:http://blog.csdn.net/jiankunking/article/details/52143504

  4. jdk动态代理使用及原理

    jdk动态代理的使用 1.创建实现InvocationHandler接口的类,实现invoke(Object proxy, Method method, Object[] args)接口,其中invo ...

  5. Java JDK 动态代理实现和代码分析

    JDK 动态代理 内容 一.动态代理解析 1. 代理模式 2. 为什么要使用动态代理 3. JDK 动态代理简单结构图 4. JDK 动态代理实现步骤 5. JDK 动态代理 API 5.1 java ...

  6. JDK 动态代理 源码简单分析

    代理的作用就是在访问真实对象之前或者之后可以额外加入一些操作. JDK  的动态代理 只需要 5 步. 真实对象必须要实现接口,首先创建一个接口 public interface HelloWorld ...

  7. jdk动态代理 案例

    import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflec ...

  8. 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)

    代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...

  9. 解析JDK动态代理实现原理

    JDK动态代理使用实例 代理模式的类图如上.关于静态代理的示例网上有很多,在这里就不讲了. 因为本篇讲述要点是JDK动态代理的实现原理,直接从JDK动态代理实例开始. 首先是Subject接口类. p ...

随机推荐

  1. 【软件测试部署基础】npm的认识

    1. npm简介 先来看下官方介绍: npm makes it easy for JavaScript developers to share and reuse code, and it makes ...

  2. c++11-17 模板核心知识(十四)—— 解析模板之依赖型模板名称(.template/->template/::template)

    tokenization与parsing 解析模板之类型的依赖名称 Dependent Names of Templates Example One Example Two Example Three ...

  3. ARC109F - 1D Kingdom Builder

    一行格子,其中小于\(0\)的格子为白色,大于\(n\)的格子为黑色,中间的格子颜色由题目给出. 有一些格子需要被标记.标记按照以下规则进行:选择一个颜色\(c\),找到一个未标记的 旁边有标记点的 ...

  4. ORCHARD WOODEN GATE

    狗: 代码小盒子 爆零秘籍 备忘录 任务计划 核心算法: 搜索/枚举/贪心 dp 分治 数据结构: 并查集 ST表 堆 线段树 树状数组 分块 树套树 平衡树 LCT 莫队 字符串: 哈希 Trie ...

  5. 你必须要知道的HTTP协议原理

    1 基本概念 HTTP协议:基于TCP协议之上实现的无状态.全文本的标准通信协议. 客户端:例如pc浏览器,移动应用端,第三方服务器等能发起http访问的设备. 服务器:能够接受HTTP协议请求,并且 ...

  6. Day5 - 04 函数的参数-可变参数*

    传入的参数的个数是可变的. 例子:定义一个函数,通过给出一组数,返回这组数中最大值与最小值的和.    def msum(numbers):        r = max(numbers) + min ...

  7. 【面试专栏】ArrayList 非线程安全案例并提供三种解决方案

    1. 复现问题 import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * 复现问题 * * @au ...

  8. 为了Java微信支付V3开发包,我找出了微信支付文档至少六个错误

    1. 前言 最近忙的一批,难得今天有喘气的机会就赶紧把最近在开发中的一些成果分享出来.前几日分享了自己写的一个微信支付V3的开发包payment-spring-boot-starter,就忙里偷闲完善 ...

  9. 【JAVA基础】静态方法

    /* * 与Python的静态单例比较: * 一样是需要加上static方法才可以直接调用类里面的私有方法 * * Python的类方法上 加上装饰器@staticmethod就可以不用实例化类而直接 ...

  10. js 乘除算法 浮点 精度解决办法

    js中进行浮点数运算时容易出现精度问题 1) 除法函数 //说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显.这个函数返回较为精确的除法结果. //调用:accDiv(a ...