自己完成一个jdk动态代理

 

自己完成一个jdk动态代理

1、自定义类加载器
 

package proxy.custom;

import java.io.*;

public class GPClassLoader extends ClassLoader {
    private File classPathFile;

    public GPClassLoader() {
        String classPath = GPClassLoader.class.getResource("").getPath();
        this.classPathFile = new File(classPath);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String className = GPClassLoader.class.getPackage().getName() + "." + name;
        if (classPathFile != null) {
            File classFile = new File(classPathFile, name.replaceAll("\\.", "/")+".class");
            System.out.println(classFile);
            if (classFile.exists()) {
                FileInputStream in = null;
                ByteArrayOutputStream out = null;

                try {
                    in = new FileInputStream(classFile);
                    out = new ByteArrayOutputStream();
                    byte[] buf = new byte[1024];
                    int len;
                    while ((len = in.read(buf)) != -1) {
                        out.write(buf, 0, len);
                    }
                    return defineClass(className, out.toByteArray(), 0, out.size());
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (in != null) {
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (out != null) {
                        try {
                            out.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return null;
    }
}

2、自定义InvocationHandler
 

package proxy.custom;

import java.lang.reflect.Method;

public interface GPInvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

3、自定义代理对象生成类GPProxy
 

package proxy.custom;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class GPProxy {
    public static  String ln="\r\n";
    public static Object newProxyInstance(GPClassLoader classLoader,Class<?>[] interfaces,GPInvocationHandler h){
        //动态生成源代码,java文件
        String str=generateSrc(interfaces);
        //java文件输出到磁盘
        String filePath=GPProxy.class.getResource("").getPath();
        System.out.println("filePath:"+filePath);
        File f=new File(filePath+"$Proxy0.java");
        FileWriter fw= null;
        try {
            fw = new FileWriter(f);
            fw.write(str);
            fw.flush();
            fw.close();
        //编译成.class文件
        JavaCompiler compiler=ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager manage=compiler.getStandardFileManager(null,null,null);
        Iterable iterable=manage.getJavaFileObjects(f);
        JavaCompiler.CompilationTask task = compiler.getTask(null,manage,null,null,null,iterable);
        task.call();
        manage.close();
        f.delete();
        //编译生成的.class文件加载到JVM中
        Class proxyClass=classLoader.findClass("$Proxy0");
        Constructor constructor=proxyClass.getConstructor(GPInvocationHandler.class);
        //返回字节码重组以后的新的代理对象
        return constructor.newInstance(h);
        } catch (IOException e) {
            e.printStackTrace();
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }





        return null;
    };

    private static String generateSrc(Class<?>[] interfaces){
        StringBuffer sb=new StringBuffer();
        sb.append("package proxy.custom;"+ln);
        sb.append("import proxy.Person;"+ln);
        sb.append("import java.lang.reflect.Method;");
        sb.append("public class $Proxy0 implements "+interfaces[0].getName()+"{"+ln);
        sb.append("GPInvocationHandler h;");
        sb.append("public $Proxy0(GPInvocationHandler h){"+ln);
        sb.append("this.h=h;");
        sb.append("}");

        for (Method m:interfaces[0].getMethods()
             ) {
            sb.append("public "+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();
    }

}

4、代理生成类CustomProxy
 

package proxy.custom;

import proxy.Person;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class CustomProxy implements GPInvocationHandler
    {
        //被代理的对象
        private Person target;

        public Object getProxy(Person target){
        this.target=target;
        Class<?> clazz=target.getClass();
        //生成代理对象
        return GPProxy.newProxyInstance(new GPClassLoader(),clazz.getInterfaces(),this);
    }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("这里是珍爱网,已拿到你的要求,帮你寻找真爱");
        method.invoke(this.target,args);
        System.out.println("有情人终成眷属");
        return null;
    }
}

5、测试:

package proxy.custom;

import proxy.Person;
import proxy.jdk.JDKProxy;
import proxy.jdk.XiaoMing;

public class CustomProxyTest {
    public static void main(String[] args) {
        Person xiaoming =new XiaoMing();
        Person person=(Person) new CustomProxy().getProxy(xiaoming);
        System.out.println(person.getClass());
        person.findLove();

    }
}


自己完成一个jdk动态代理