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不应该出现在编译文件这个地方。

 

posted @ 2020-04-18 11:33  思思博士  阅读(288)  评论(0编辑  收藏  举报