手写实现JDK的动态代理
Posted itzhoucong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写实现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("我叫张三,性别女,我找对象的要求如下: "); 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 = " "; 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的动态代理的主要内容,如果未能解决你的问题,请参考以下文章