手写实现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代理机制,为什么接口不用实现类也能代理? 好了,废话不 ...
随机推荐
- [RoarCTF2019]黄金6年
嘶吼CTF的杂项题 这道题目比较简单 下载之后是一个mp4文件,黄金六年,害,亲爱的热爱的里面的梗 使用010 Editor打开视频文件,发现最下面有base64编码 UmFyIRoHAQAzkrXl ...
- 图 Graph
本文主要内容为:图的定义以及基本术语 图的定义 图 图G的组成:由 数据元素的集合E 和 数据间的关系集合E 组成,记作:G = <V, E> 顶点 (vertex):数据元素,V就是顶点 ...
- LeetCode初级算法之字符串:344 反转字符串
反转字符串 题目地址:https://leetcode-cn.com/problems/reverse-string/ 编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 char[] ...
- 图论-zkw费用流
图论-zkw费用流 模板 这是一个求最小费用最大流的算法,因为发明者是神仙zkw,所以叫zkw费用流(就是zkw线段树那个zkw).有些时候比EK快,有些时候慢一些,没有比普通费用流算法更难,所以学z ...
- Anno 让微服务、混合编程更简单(Net love Java)
在社区或者QQ群我们经常看到有人争辩编程语言的好坏,只要一提起这个话题常常就能引来很多人参与,往往最后就变成了一群人几个小时的骂战.今天我们要说的是如何让Java和.Net(甚至更多语言)相结合.充分 ...
- Map、Debug追踪
Map集合 概述 现实生活中,我们常会看到这样一种集合:IP地址和主机名,身份证号和个人,系统用户名与系统用户对象等,这种一一对应的关系,我们把它称之为映射.Java当中提供了专门的集合类用来 ...
- mysql主从双机keepalived配置
1.关闭selinux SELINUX=disabled 2.yum安装keepalived yum install -y keepalived 3.修改配置文件 主库配置文件: ! Configur ...
- SpringBoot基于JustAuth实现第三方授权登录
1. 简介 随着科技时代日渐繁荣,越来越多的应用融入我们的生活.不同的应用系统不同的用户密码,造成了极差的用户体验.要是能使用常见的应用账号实现全应用的认证登录,将会更加促进应用产品的推广,为生活 ...
- 解决idea 中web项目无法正常显示的问题
- 仵航说 Vue项目如何打包并发布到linux服务器 仵老大
1,打包 1.1首先你会在本地编辑好你的代码, 1.2然后在控制台输入 npm run build npm run build 1.3稍等片刻就打包完毕 2,位置 2.1打包完毕之后会在项目中生成一个 ...