手写实现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代理机制,为什么接口不用实现类也能代理? 好了,废话不 ...
随机推荐
- PyQt(Python+Qt)学习随笔:gridLayout的layoutRowStretch和layoutColumnStretch属性
Qt Designer中网格布局中,layoutRowStretch和layoutColumnStretch两个属性分别设置网格布局中行之间和列之间的拉伸因子,如图: 但是QGridLayout并没有 ...
- 大数据技术体系 && NoSQL数据库的基本原理
1.NoSQL产生的原因 目前关系型数据库难以应对日益增多的海量数据,横向的分布式扩展能力比较弱,因此构建出非关系型数据库(所谓的NoSQL),其目的是为了构建一种结构简单.分布式.易扩展.效率高且使 ...
- bugku never give up
打开网页,看到?id=1,很容易想到了爆破. 然后bp抓包爆破.(传说中的一秒爆破.) 看到了 1p.html . 直接访问 缓缓打出一个?(这是个锤子o,本来以为这里有flag,但是,这真的是论坛啊 ...
- x++ 和 ++x的区别
很多编程语言都会有x++和++x的问题,两个到底是怎么回事? 一个先执行一个后执行的区别 var x = 0; console.log(x++);//0 遇到x++当前执行值不变 console.lo ...
- Vmare虚拟机网络连接方式桥接模式+桥接模式+主机模式
虚拟机网络连接模式 最近在学习虚拟机和计算机网络,在网上看了一些关于虚拟机网络连接方式的介绍 这篇文章写的不错:https://www.cnblogs.com/luxiaodai/p/9947343. ...
- IE各版本和Windows的关系
- Python零散知识点记录
1.关于setdefaultencoding之前必须reload(sys): 要在调用setdefaultencoding时必须要先reload一次sys模块,因为这里的import语句其实并不是sy ...
- swiper4使用教程-填坑
本篇博客用于记录使用swiper插件中的一些关键点: 首先附上官网地址:https://www.swiper.com.cn/ ios中使用swiper的坑: /*解决swiper中苹果点击变暗,在cs ...
- 手动实现Promise.all()
Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例. Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每 ...
- DVWA各等级文件上传漏洞
file upload 文件上传漏洞,攻击者可以通过上传木马获取服务器的webshell权限. 文件上传漏洞的利用是 够成功上传木马文件, 其次上传文件必须能够被执行, 最后就是上传文件的路径必须可知 ...