手写实现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");
} }
自定义InvocationHandler接口
package com.zhoucong.custom; import java.lang.reflect.Method; public interface GPInvocationHandler { public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable; }
代理类
package com.zhoucong.custom; import java.lang.reflect.Method; import com.zhoucong.proxy.jdk.Person; public class GPMeiPo implements GPInvocationHandler{ private Person target; // 获取被代理人的个人资料
public Object getInstance(Person target) throws Exception {
this.target = target;
Class clazz = target.getClass();
System.out.println("被代理对象的class是:"+ clazz);
return GPProxy.newProxyInstance(new GPClassLoader(), clazz.getInterfaces(), this); } @Override
public Object invoke(Object proxy, 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.custom; import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider; /**
* 生成代理对象的代码
*
* @author ZhouCong
*
*/
public class GPProxy { private static String ln = "\r\n"; public static Object newProxyInstance(GPClassLoader loader, Class<?>[] interfaces, GPInvocationHandler h)
throws IllegalArgumentException {
try {
// 1.生成源代码
String proxySrc = generateSrc(interfaces[0]); // 2.将生成的源代码输出到磁盘,保存.java文件
String path = GPProxy.class.getResource("").getPath();
File f = new File(path + "$Proxy0.java");
FileWriter fw = new FileWriter(f);
fw.write(proxySrc);
fw.flush();
fw.close(); // 3.编译源代码,并且生成.class文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
Iterable iterable = manager.getJavaFileObjects(f);
CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
task.call();
manager.close(); // 4.将class文件中的内容,动态加载到JVM中
Class<?> proxyClass = loader.findClass("$Proxy0");
Constructor<?> constructor = proxyClass.getConstructor(GPInvocationHandler.class);
f.delete(); //删除生成的Java文件 // 5.返回被代理后的代理对象
return constructor.newInstance(h); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
} /**
* 生成代码
* @param interfaces
* @return
*/
private static String generateSrc(Class<?> interfaces) { StringBuffer src = new StringBuffer();
src.append("package com.zhoucong.custom;" + ln);
src.append("import java.lang.reflect.Method;" + ln);
src.append("public class $Proxy0 implements " + interfaces.getName() + "{" + ln);
src.append("GPInvocationHandler h;" + ln);
src.append("public $Proxy0(GPInvocationHandler h){" + ln);
src.append("this.h = h;" + ln);
src.append("}" + ln); for (Method m : interfaces.getMethods()) {
src.append("public " + m.getReturnType().getName() + " " + m.getName() + "() {" + ln);
src.append("try {" + ln);
src.append("Method m = " + interfaces.getName() + ".class.getMethod(\"" + m.getName() +"\",new Class[]{});" + ln);
src.append("this.h.invoke(this,m,null);" + ln);
src.append("} catch(Throwable e){e.printStackTrace();}" + ln);
src.append("}" + ln);
} src.append("}");
return src.toString();
};
}
自定义ClassLoader类
package com.zhoucong.custom; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; /**
* 代码生成、编译、重新动态load到JVM中
* @author ZhouCong
*
*/
public class GPClassLoader extends ClassLoader{ private File baseDir; public GPClassLoader() {
String path = GPClassLoader.class.getResource("").getPath();
this.baseDir = new File(path);
} @Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String className = GPClassLoader.class.getPackage().getName() + "." + name;
if(baseDir != null) {
File classFile = new File(baseDir,name.replaceAll("\\.", "/")+".class");
if(classFile.exists()) {
FileInputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new FileInputStream(classFile);
out = new ByteArrayOutputStream();
byte [] buff = new byte[1024];
int len;
while((len = in.read(buff)) != -1) {
out.write(buff,0,len);
}
return defineClass(className,out.toByteArray(),0,out.size()); }catch (Exception e) {
e.printStackTrace();
}finally { if(null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 删除class文件
classFile.delete();
}
} } return null;
} }
运行类
package com.zhoucong.proxy.jdk; import com.zhoucong.custom.GPMeiPo; public class TestFindLove { public static void main(String[] args) { try { Person obj = (Person) new GPMeiPo().getInstance(new Zhangsan());
System.out.println(obj.getClass());
obj.findlove();
} catch (Exception e) {
e.printStackTrace();
}
} }
手写实现JDK的动态代理的更多相关文章
- JDK动态代理深入理解分析并手写简易JDK动态代理(下)
原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-05/27.html 作者:夜月归途 出处:http://www.guitu ...
- JDK动态代理深入理解分析并手写简易JDK动态代理(上)
原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-03/27.html 作者:夜月归途 出处:http://www.guitu ...
- JAVA JDK的动态代理反射实现
动态代理类使用到了一个接口InvocationHandler和一个代理类Proxy ,这两个类配合使用实现了动态代理的功能. 什么是动态代理呢? 普通代理类是指: 给每个具体类写一个代理类,以后要使 ...
- jdk的动态代理
至于jdk的动态代理怎么用此处并不多说,现在是更深一步的理解,jdk的Proxy类到底做了什么. Proxy.newProxyInstance可以生成代理类,此方法有三个参数(ClassLoader ...
- 基于 JDK 的动态代理机制
『动态代理』其实源于设计模式中的代理模式,而代理模式就是使用代理对象完成用户请求,屏蔽用户对真实对象的访问. 举个最简单的例子,比如我们想要「FQ」访问国外网站,因为我们并没有墙掉所有国外的 IP,所 ...
- JDK的动态代理机制
JDK Proxy OverView jdk的动态代理是基于接口的,必须实现了某一个或多个随意接口才干够被代理,并且仅仅有这些接口中的方法会被代理.看了一下jdk带的动态代理api.发现没有样例实在是 ...
- JDK 原生动态代理是怎么实现的 + 面试题
JDK 原生动态代理是怎么实现的 + 面试题 反射 反射机制是 Java 语言提供的一种基础功能,赋予程序在运行时自省(introspect)的能力.简单来说就是通过反射,可以在运行期间获取.检测和调 ...
- 代理模式详解:静态代理+JDK/CGLIB 动态代理实战
1. 代理模式 代理模式是一种比较好的理解的设计模式.简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标 ...
- JDK的动态代理-----为接口进行代理
JDK的动态代理是必须掌握的,动态代理的好处就不用我多说了吧 :) 小弟最近在研究mybatis的源码实现,就开始了解mybatis的Mapper代理机制,为什么接口不用实现类也能代理? 好了,废话不 ...
随机推荐
- 使用Fiddle修改请求数据
修改请求数据 以淘宝网为例 命令行中输入bpu 及要拦截的请求地址,如bpu https://s.taobao.com/search 在搜索栏中输入"面包机" 可以看到拦截到的请求 ...
- RedHat操作指令第3篇
系统信息 arch 显示机器的处理器架构 uname -m 显示机器的处理器架构 uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS / DMI) ...
- python 读取excel表格内不同类型的数据
不同类型数据对应值: #coding=utf-8 import os import xlrd from datetime import datetime,date newparh = os.chdir ...
- LeetCode初级算法之数组:283 移动零
移动零 题目地址:https://leetcode-cn.com/problems/move-zeroes/ 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺 ...
- 深入剖析HashMap
前言 很高兴遇见你~ HashMap是一个非常重要的集合,日常使用也非常的频繁,同时也是面试重点.本文并不打算讲解基础的使用api,而是深入HashMap的底层,讲解关于HashMap的重点知识.需要 ...
- 【Alpha冲刺阶段】Scrum Meeting Daily5
[Alpha冲刺阶段]Scrum Meeting Daily5 1.会议简述 会议开展时间 2020/5/27 8:30-9:00 PM 会议基本内容摘要 大家讲述了自己的任务完成情况以及遇到的问题 ...
- CSS全览_选择符+特指+单位+字体
CSS全览_选择符+特指+单位+字体 目录 CSS全览_选择符+特指+单位+字体 1. CSS样式 2. 选择符 3. 特指度和层叠 4. 值和单位 5. 字体 作者: https://www.cnb ...
- 【题解】「CF675A」Infinite Sequence
我用的是:分类讨论+暴力 其中分类讨论中,我用了一种namespace名命名空间.如果: \(c = 0\) : 当 \(a == b\) 时,输出 \(YES\) 否则 \(NO\) \(c < ...
- AcWing 309. 装饰围栏
题目链接 这道题与下一章的数位\(dp\)解题思路十分一致. 把寻找答案变成按位(并且是字典序从小到大)枚举当前这一位可以填的情况. 通过\(dp\)预处理的信息告诉我们可行性,就可以把答案紧逼到一个 ...
- 我对js数据类型的理解和深浅(copy)的应用场景
本人毕业一所专科院校,所学专业是计算机应用技术,在大学时对前端有了一定的了解之后,觉得自己对前端的兴趣十分强烈,开始自学前端,一路上也是坎坎坷坷,也有想要放弃的时候,还好坚持了下来,并且从事前端开发已 ...