手写一个动态代理实现,手写Proxy,手写ClassLoader,手写InvocationHandler
整个过程中用到了手写类加载器,
手写动态生成java代码
手写编译代码
最后实现动态代理
手写Proxy示例代码:
package com.example.demo.proxy.custom;import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;public class GPProxy {public static final String ln = "\r\n";public static Object newProxyInstance(GPClassLoader classLoader,Class<?>[] interfaces,GPInvocationHandler h){//生成java代码String s = generateSrc(interfaces);//将代码写入到本地String path = GPProxy.class.getResource("").getPath();System.out.println(path);File file = new File(path + "$Proxy0.java");FileOutputStream fileOutputStream = null;try {fileOutputStream = new FileOutputStream(file);fileOutputStream.write(s.getBytes());fileOutputStream.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {if(fileOutputStream != null){try {fileOutputStream.close();} catch (IOException e) {e.printStackTrace();}}}//编译代码JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager manager = javaCompiler.getStandardFileManager(null, null, null);Iterable<? extends JavaFileObject> javaFileObjects = manager.getJavaFileObjects(file);JavaCompiler.CompilationTask task = javaCompiler.getTask(null, manager, null, null, null, javaFileObjects);task.call();try {manager.close();} catch (IOException e) {e.printStackTrace();}//删除.java文件file.delete();//将代码读取到jvm,并生成对应的类Object o = null;try {Class<?> clazz = classLoader.findClass("$Proxy0");Constructor<?> constructor = clazz.getConstructor(GPInvocationHandler.class);o = constructor.newInstance(h);} catch (ClassNotFoundException | NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}//返回字节码重组以后的新的代理对象return o;}private static String generateSrc(Class<?>[] interfaces ) {StringBuffer sb = new StringBuffer();sb.append(GPProxy.class.getPackage() + ";" + ln);sb.append("import " + interfaces[0].getPackage().toString().substring(8) + "." + interfaces[0].getSimpleName() +";" + ln);sb.append("import java.lang.reflect.*;" + ln);sb.append("public class $Proxy0 implements " + interfaces[0].getSimpleName() + "{" + ln);sb.append("GPInvocationHandler h;" + ln);//初始化GPInvocationHandlersb.append("public $Proxy0(GPInvocationHandler h){" + ln);sb.append("this.h = h;" + ln);sb.append("}" + ln);//循环调用方法for (Method m : interfaces[0].getMethods()) {sb.append("public final " + m.getReturnType().getName() + " " + m.getName() + "(){" + ln);sb.append("try{" + ln);sb.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + m.getName() + "\", new Class[]{});" + ln);sb.append("this.h.invoke(this, m, null);" + ln);sb.append("}catch(Throwable e){" + ln);sb.append("e.printStackTrace();" + ln);sb.append("}" + ln);sb.append("}" + ln);}sb.append("}" + ln);return sb.toString();}
}
手写ClassLoader示例代码:
package com.example.demo.proxy.custom;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;public class GPClassLoader extends ClassLoader{private File classPathFile;public GPClassLoader(){String classPath = GPClassLoader.class.getResource("").getPath();this.classPathFile = new File(classPath);}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {String className = GPClassLoader.class.getPackage().getName() + "." + name;if(classPathFile != null){File classFile = new File(classPathFile, 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 = 0;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 {try {if(in != null)in.close();} catch (IOException e) {e.printStackTrace();}try {if(out != null)out.close();} catch (IOException e) {e.printStackTrace();}}}}return null;}
}
手写InvocationHandler
package com.example.demo.proxy.custom;import java.lang.reflect.Method;@FunctionalInterface
public interface GPInvocationHandler {public Object invoke(Object proxy, Method method, Object[] args);
}
动态代理类的示例代码:
package com.example.demo.proxy.custom;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class GPMeipo implements GPInvocationHandler{Object object;public Object getInstance(Object object){this.object = object;Object o = GPProxy.newProxyInstance(new GPClassLoader(), object.getClass().getInterfaces(), this);return o;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) {System.out.println("媒婆拿到需求");System.out.println("媒婆匹配姑娘!");Object invoke = null;try {invoke = method.invoke(object, args);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}System.out.println("媒婆安排婚事");return invoke;}
}
测试接口的代码:
package com.example.demo.proxy;public interface Person {void findLove();void zufangzi();
}
测试被代理类的代码:
package com.example.demo.proxy;public class ZH implements Person {@Overridepublic void findLove() {System.out.println("肤白貌美大长腿!");}@Overridepublic void zufangzi() {}
}
测试手写代理类:
package com.example.demo.proxy.custom;import com.example.demo.proxy.Person;
import com.example.demo.proxy.ZH;public class CustomProxyTest {public static void main(String[] args) {Person zh = (Person) new GPMeipo().getInstance(new ZH());zh.findLove();}
}
手写一个动态代理实现,手写Proxy,手写ClassLoader,手写InvocationHandler相关推荐
- 深入理解JDK动态代理原理,使用javassist动手写一个动态代理框架
文章目录 系列文章索引 一.动手实现一个动态代理框架 1.初识javassist 2.使用javassist实现一个动态代理框架 二.JDK动态代理 1.编码实现 2.基本原理 (1)getProxy ...
- 两万字吐血总结,代理模式及手写实现动态代理(aop原理,基于jdk动态代理)
代理模式及手写实现动态代理 一.代理模式 1. 定义 2. 示例 (1)静态代理 (2)动态代理 3. 通用类图 4. 代理模式的优点 二.jdk动态代理实现原理 1. jdk动态代理源码分析(通过该 ...
- 手撸一个动态数据源的Starter 完整编写一个Starter及融合项目的过程 保姆级教程
手撸一个动态数据源的Starter! 文章目录 手撸一个动态数据源的Starter! 前言 一.准备工作 1,演示 2,项目目录结构 3,POM文件 二.思路 三.编写代码 1,定义核心注解 Ds 2 ...
- JDK的动态代理深入解析(Proxy,InvocationHandler)(转)
一.什么是动态代理 动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实.代理一般会实现它所表示的实际对象的接口.代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际 ...
- 手写Java动态代理
博客内容来自笔者微信公众号. 动态代理又包括JDK代理和CGLIB代理. MyBatis框架就用到了动态代理技术,我们只关心Dao接口,而无需关心实现类. 动态代理功能十分强大,今天记录一下本人 手动 ...
- 用python写一个动态壁纸工具
screenpv.py: use pyqt5 + opencv to open a video or camera 首先用pyqt5+opencv写一个全屏播放视频的工具 import sys imp ...
- 写一个动态爱心的C语言代码吧
好的,这是一个用 C 语言写的动态爱心的代码.需要注意,这段代码需要在 Windows 系统上运行,因为它使用了 Windows API 函数. #include <stdio.h> #i ...
- 什么是Java动态代理,如何实现一个动态代理例子
Java动态代理 一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家"委托"代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背 ...
- 做了一个动态代理 IP 池项目,邀请大家免费测试~
长期在掘金潜水, 现在打算出来创业了,目前公司在深圳. 做了点啥呢, 就是给爬虫用的动态代理 IP 池啦. 目前运行很稳定, 邀请大家来免费测试使用, 获取免费激活码:微信公众号"2808p ...
最新文章
- Android之了解ThreadLocal
- Spring Framework(框架)整体架构
- 监听 html dom 变化,如何监听页面 DOM 变动并高效响应
- latex中怎样使公式居中_LaTeX_多行公式对齐居中的同时选择性的加编号
- pandas 股票分析图
- WP8.1学习系列(第二章)——Toast通知
- centoss7 yum 安装 wget
- 完美企业网站的101项指标
- 18.go 日志监控系统
- php使用自定义ip,PHP跨平台获取服务器IP地址自定义函数分享
- 百度云无限速下载工具:JDownloader 2 for Mac
- (Cys-RGD)包被CdTe量子|3-巯基丙酸(MPA)包被近红外发光CdTe量子
- SaltStack配置管理
- 敖丙带你设计【秒杀系统】
- RGB、CMY、HSV、HSL颜色空间
- 4.一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?
- noi2008 假面舞会
- caspase家族的特点_caspase家族
- Spring集成MyBatis
- linux 内核学习11-内核模块参数
热门文章
- C语言printf函数详解和示例
- 红帽RHEL8和RHEL7有什么区别?
- 停止、启动或重新启动 VMware vCenter Server Appliance 6.x 及更高版本上的服务 (2109887)
- Java基础学习总结(170)——Java8并发工具类CompletableFuture学习总结
- Java基础学习总结(162)——如何保证线程安全?
- Java基础学习总结(29)——浅谈Java中的Set、List、Map的区别
- mysql date转换_mysql DATE 转换 ip to int
- java中输入两个数组并显示_java-将输入存储在两个相关的数组中
- Android:活动中的提示 (Tosat) 和打印信息 (Log)
- python + selenium - selenium常用元素定位