JDK动态代理之跳过动态代理徒手编写动态代理
我的这篇博客分析了动态代理对象是如何生成的 java动态代理之JDK源码解析,
JDK动态代理的对象是JDK在没有产生任何文件的条件下,JVM直接通过字节数组生成的对象。
可是这种模式我们是没办法复制的。
你可能是一个非常牛逼的高手,能够直接编写存放字节码文件的字节数组;然而没有一个地方让你能够直接将这个数组载入虚拟机。
如果我们需要编写一个动态的代理对象,只能一步一步的调用jdk提供的接口方法。
步骤大致是这样的:创建接口文件==》动态生成java文件内容==》程序创建java文件==》调用Java编译功能==>载入虚拟机==》利用反射生成代理对象
接口文件IPeople:
package c.b; public interface IPeople { void say(); }
动态生成java文件内容
public static String createContent(){ final String ln="\r\n"; StringBuilder sb=new StringBuilder(); sb.append("package c.b;"+ln); sb.append("public class People implements IPeople { "+ln); sb.append("@Override"+ln); sb.append("public void say() {"+ln); sb.append("System.out.println(\"say......\");"+ln); sb.append("}"+ln); sb.append("}"+ln); return sb.toString(); };
程序创建java文件
public static File createfile(String src) throws IOException { String filePath=MyProxy.class.getResource("").getPath(); File f=new File(filePath+"People.java"); FileWriter fw=new FileWriter(f); fw.write(src); fw.flush(); fw.close(); return f; }
调用Java编译功能
public static void compier(File f) throws IOException { JavaCompiler compier= ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager manage=compier.getStandardFileManager(null,null,null); Iterable iterable=manage.getJavaFileObjects(f); JavaCompiler.CompilationTask task=compier.getTask(null,manage,null,null,null,iterable); task.call(); manage.close(); }
载入虚拟机 java 自定义类加载器
public static Object jvmLoad() throws Exception { //包+类名 Class proxyClass=IPeople.class.getClassLoader().loadClass("c.b.People"); return proxyClass; }
利用反射生成代理对象
public static Object newInstance(Class proxyClass) throws Exception { //通过无参构造方法实例化 Object object=proxyClass.getDeclaredConstructor(null).newInstance(); return object; }
main入口方法
public static void main(String[] args) throws Exception { String src=createContent(); File f=createfile(src); compier(f); Class clazz=jvmLoad(); IPeople people=(IPeople) newInstance(clazz); people.say();
f.delete(); }
记得最后调用删除文件功能,People.java不应该出现在编译文件这个地方。