整个过程中用到了手写类加载器,
手写动态生成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相关推荐

  1. 深入理解JDK动态代理原理,使用javassist动手写一个动态代理框架

    文章目录 系列文章索引 一.动手实现一个动态代理框架 1.初识javassist 2.使用javassist实现一个动态代理框架 二.JDK动态代理 1.编码实现 2.基本原理 (1)getProxy ...

  2. 两万字吐血总结,代理模式及手写实现动态代理(aop原理,基于jdk动态代理)

    代理模式及手写实现动态代理 一.代理模式 1. 定义 2. 示例 (1)静态代理 (2)动态代理 3. 通用类图 4. 代理模式的优点 二.jdk动态代理实现原理 1. jdk动态代理源码分析(通过该 ...

  3. 手撸一个动态数据源的Starter 完整编写一个Starter及融合项目的过程 保姆级教程

    手撸一个动态数据源的Starter! 文章目录 手撸一个动态数据源的Starter! 前言 一.准备工作 1,演示 2,项目目录结构 3,POM文件 二.思路 三.编写代码 1,定义核心注解 Ds 2 ...

  4. JDK的动态代理深入解析(Proxy,InvocationHandler)(转)

    一.什么是动态代理 动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实.代理一般会实现它所表示的实际对象的接口.代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际 ...

  5. 手写Java动态代理

    博客内容来自笔者微信公众号. 动态代理又包括JDK代理和CGLIB代理. MyBatis框架就用到了动态代理技术,我们只关心Dao接口,而无需关心实现类. 动态代理功能十分强大,今天记录一下本人 手动 ...

  6. 用python写一个动态壁纸工具

    screenpv.py: use pyqt5 + opencv to open a video or camera 首先用pyqt5+opencv写一个全屏播放视频的工具 import sys imp ...

  7. 写一个动态爱心的C语言代码吧

    好的,这是一个用 C 语言写的动态爱心的代码.需要注意,这段代码需要在 Windows 系统上运行,因为它使用了 Windows API 函数. #include <stdio.h> #i ...

  8. 什么是Java动态代理,如何实现一个动态代理例子

    Java动态代理 一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家"委托"代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背 ...

  9. 做了一个动态代理 IP 池项目,邀请大家免费测试~

    长期在掘金潜水, 现在打算出来创业了,目前公司在深圳. 做了点啥呢, 就是给爬虫用的动态代理 IP 池啦. 目前运行很稳定, 邀请大家来免费测试使用, 获取免费激活码:微信公众号"2808p ...

最新文章

  1. Android之了解ThreadLocal
  2. Spring Framework(框架)整体架构
  3. 监听 html dom 变化,如何监听页面 DOM 变动并高效响应
  4. latex中怎样使公式居中_LaTeX_多行公式对齐居中的同时选择性的加编号
  5. pandas 股票分析图
  6. WP8.1学习系列(第二章)——Toast通知
  7. centoss7 yum 安装 wget
  8. 完美企业网站的101项指标
  9. 18.go 日志监控系统
  10. php使用自定义ip,PHP跨平台获取服务器IP地址自定义函数分享
  11. 百度云无限速下载工具:JDownloader 2 for Mac
  12. (Cys-RGD)包被CdTe量子|3-巯基丙酸(MPA)包被近红外发光CdTe量子
  13. SaltStack配置管理
  14. 敖丙带你设计【秒杀系统】
  15. RGB、CMY、HSV、HSL颜色空间
  16. 4.一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?
  17. noi2008 假面舞会
  18. caspase家族的特点_caspase家族
  19. Spring集成MyBatis
  20. linux 内核学习11-内核模块参数

热门文章

  1. C语言printf函数详解和示例
  2. 红帽RHEL8和RHEL7有什么区别?
  3. 停止、启动或重新启动 VMware vCenter Server Appliance 6.x 及更高版本上的服务 (2109887)
  4. Java基础学习总结(170)——Java8并发工具类CompletableFuture学习总结
  5. Java基础学习总结(162)——如何保证线程安全?
  6. Java基础学习总结(29)——浅谈Java中的Set、List、Map的区别
  7. mysql date转换_mysql DATE 转换 ip to int
  8. java中输入两个数组并显示_java-将输入存储在两个相关的数组中
  9. Android:活动中的提示 (Tosat) 和打印信息 (Log)
  10. python + selenium - selenium常用元素定位