手写一个动态代理实现,手写Proxy,手写ClassLoader,手写InvocationHandler

star2017 1年前 ⋅ 1756 阅读

整个过程中用到了手写类加载器,
手写动态生成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);
            //初始化GPInvocationHandler
            sb.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);
    }

    @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");
            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;
    }

    @Override
    public 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 {
    @Override
    public void findLove() {
        System.out.println("肤白貌美大长腿!");
    }

    @Override
    public 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();
    }
}
更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: