天天看点

手写JDK动态代理

一,JDK动态代理

    在纯手写动态代理前,首先分析一套标准JDK动态代理的执行流程。

1,目标类顶层接口

public interface ProxyInterface {

    public void targetMethod();
}
           

2,目标类

public class JDKProxyTarget implements ProxyInterface{

    @Override
    public void targetMethod() {
        System.out.println("代理方法...");
    }
}
           

3,代理类

public class JDKProxy {

    private ProxyInterface proxyInterface;

    public JDKProxy(ProxyInterface proxyInterface) {
        this.proxyInterface = proxyInterface;
    }

    public Object instanceProxy() {
        System.out.println("代理方法开始...");
        ProxyInterface instance = (ProxyInterface) Proxy.newProxyInstance(
                proxyInterface.getClass().getClassLoader(),
                proxyInterface.getClass().getInterfaces(),
                new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                method.invoke(proxyInterface, args);
                System.out.println("代理方法结束...");
                return null;
            }
        });
        return instance;
    }

}
           

4,测试类

public class JDKProxyTest {
    public static void main(String[] args) throws Exception {
        JDKProxy proxy = new JDKProxy(new JDKProxyTarget());
        ProxyInterface proxyInterface = (ProxyInterface) proxy.instanceProxy();
        System.out.println(proxyInterface.getClass());
        proxyInterface.targetMethod();
    }
}
           
手写JDK动态代理

5,代码解析

    a,Proxy.newInstance()方法

        * 第一个参数为目标类的类加载器

        * 第二个参数为目标类的接口集合,JDK动态代理目标类必须实现一个接口,这是为了保证生成的代理类和目标类之前的强一致性关系

        * 第三个参数为InvocationHandler接口的实现类,这里直接通过匿名内部类实现,重写了invoke方法

    b,InvocationHandler接口实现类

        * 实现该类必须重写invoke()方法,动态代理实现在代理类中该接口的实现类调用该方法,并在该方法中反射执行该方法完成整个动态代理流程;

        * 第一个参数为生成的动态代理对象;

        * 第二个参数为动态代理在客户端执行的方法;

        * 第三个参数为该方法的参数列表;

        * 通过反射来完成方法调用;

    c,通过a步骤后,JDK会虚拟生成一个$Proxy0类,该类也实现了目标类实现的接口,从而多态返回该虚拟类对象,可以通过代码输出该类

    * 代码

public class JDKProxyTest {
    public static void main(String[] args) throws Exception {
        JDKProxy proxy = new JDKProxy(new JDKProxyTarget());
        ProxyInterface proxyInterface = (ProxyInterface) proxy.instanceProxy();
        System.out.println(proxyInterface.getClass());
        proxyInterface.targetMethod();

        byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{ProxyInterface.class});
        FileOutputStream outputStream = new FileOutputStream("E:\\$Proxy0.class");
        outputStream.write(bytes);
        outputStream.close();
    }
}
           

    * $Proxy0类 --- 生成为.class文件,直接通过IDEA进行反编译

手写JDK动态代理
public final class $Proxy0 extends Proxy implements ProxyInterface {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void targetMethod() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m3 = Class.forName("com.gupao.designpattern.proxy.jdk.ProxyInterface").getMethod("targetMethod", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
           

    d, 可以看到该虚拟类继承Proxy类并实现了目标类顶层接口,并反射获取了目标类中的所有方法的Method对象;

    e, 同时,虚拟类也同时重写了目标类的所有方法,并通过下列方式进行调用

super.h.invoke(this, m3, (Object[])null);
           

        super : 指该代理类的超类,也就是Proxy;

        h : 点进源码可以看到这样一行声明

protected InvocationHandler h;
           

 在虚拟类的构造器中,也获取了InvocationHandler的引用,所以,这里的h,指的也就是在匿名内部类定义的实现类对象;

        h.invoke():就是调用匿名内部类中重写的invoke()方法,分别传递参数该对象(this),执行的方法(method),方法参数(null);

二,手写动态代理步骤分析

    从上面标准的JDK动态流程可以看出,手写动态代理,需要这样几个类

    1,SelfProxy类,定义newInstance()方法,进行代理对象创建

        * 在该方法中首先需要输出代理类的.java文件

        * 编译该.java文件生成.class文件

        * 通过类加载器加载该.class文件

        * 生成该.class文件的事例对象作为代理对象返回

    2,SelfInvocationHandler接口,定义invoke()方法,在代理类中进行目标方法调用

        * 在.java文件中,定义构造器,传递该类引用

        * 通过SelfInvocationHandler实现类对象调用invoke()方法,实现代理方式的方法调用

    3,SelfClassloader,自定义类加载器,继承JDK的ClassLoader类,实现自定义的加载方式

    4,SelfJDKProxy,实现SelfInvocationHandler接口,重写invoke()方法,实现最终方法运行

三,手写动态代理代码实现

1,目标类顶层接口

public interface SelfProxyInterface {

    public void targetMethod();
}
           

2,目标类

public class SelfJDKProxyTarget implements SelfProxyInterface{

    @Override
    public void targetMethod() {
        System.out.println("代理方法...");
    }
}
           

3,SelfClassLoader类 -- 自定义类加载器,加载.class到JVM内存中

public class SelfClassLoader extends ClassLoader{

    private File classPathFile;

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

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String className = SelfClassLoader.class.getPackage().getName() + "." + name;
        if (null != classPathFile) {
            File classFile = new File(classPathFile, name + ".class");
            if (classFile.exists()) {
                FileInputStream in = null;
                ByteArrayOutputStream out = null;
                try {
                    in = new FileInputStream(classFile);
                    out = new ByteArrayOutputStream();
                    byte[] bytes = new byte[1024];
                    int len;
                    while((len = in.read(bytes)) != -1) {
                        out.write(bytes, 0, len);
                    }

                    return defineClass(className, out.toByteArray(), 0, out.size());
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (null != in) {
                            in.close();
                        }
                        if (null != out) {
                            out.close();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        return null;
    }
}
           

4,SelfProxy类 -- 生成虚拟代理类,创建代理对象

public class SelfProxy {

    private static final String ENTER = "\r\n";

    public static Object newInstance(SelfClassLoader classLoader, Class<?>[] interfaces, SelfInvocationHandler h) {
        try {
            // 动态生成源代码
            String srcClass = generateSrc(interfaces);
            // 输出Java文件
            String filePath = SelfProxy.class.getResource("").getPath()  + "$ProxyO.java";
            System.out.println(filePath);
            FileWriter fileWriter = new FileWriter(filePath);
            fileWriter.write(srcClass);
            fileWriter.flush();
            fileWriter.close();
            // 编译Java文件为class文件
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
            Iterable iterable = fileManager.getJavaFileObjects(filePath);
            JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, iterable);
            task.call();
            fileManager.close();
            // 加载编译生成的class文件到JVM
            Class<?> proxyClass = classLoader.findClass("$ProxyO");
            Constructor<?> constructor = proxyClass.getConstructor(SelfInvocationHandler.class);
            // 删掉虚拟代理类
            File file = new File(filePath);
            file.delete();
            // 返回字节码重组以后的代理对象
            return constructor.newInstance(h);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String generateSrc(Class<?>[] interfaces) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("package com.gupao.designpattern.proxy.self;" + ENTER + ENTER);
        stringBuilder.append("import com.gupao.designpattern.proxy.jdk.ProxyInterface;" + ENTER);
        stringBuilder.append("import java.lang.reflect.Method;" + ENTER);
        stringBuilder.append("public class $ProxyO implements " + interfaces[0].getName() + "{" + ENTER);
            stringBuilder.append("SelfInvocationHandler h;" + ENTER);
            stringBuilder.append("public $ProxyO(SelfInvocationHandler h) {" + ENTER);
                stringBuilder.append("this.h = h;" + ENTER);
            stringBuilder.append("}" + ENTER);

        for (Method method : interfaces[0].getMethods()) {
            stringBuilder.append("public " + method.getReturnType().getName() + " " + method.getName() + "() {" + ENTER);
                stringBuilder.append("try {" + ENTER);
                    stringBuilder.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + method.getName() + "\", new Class[]{});" + ENTER);
                    stringBuilder.append("this.h.invoke(this, m, null);" + ENTER);
                stringBuilder.append("} catch(Throwable able) {" + ENTER);
                stringBuilder.append("able.getMessage();" + ENTER);
                stringBuilder.append("}" + ENTER);
            stringBuilder.append("}" + ENTER + ENTER);
        }
        stringBuilder.append("}" + ENTER);
        return stringBuilder.toString();
    }

}
           

    该类代码的具体步骤在注释中已经写明;

5,查看生成的.java文件

package com.gupao.designpattern.proxy.self;

import com.gupao.designpattern.proxy.jdk.ProxyInterface;

import java.lang.reflect.Method;

public class $ProxyO implements com.gupao.designpattern.proxy.self.SelfProxyInterface {
    SelfInvocationHandler h;

    public $ProxyO(SelfInvocationHandler h) {
        this.h = h;
    }

    public void targetMethod() {
        try {
            Method m = com.gupao.designpattern.proxy.self.SelfProxyInterface.class.getMethod("targetMethod", new Class[]{});
            this.h.invoke(this, m, null);
        } catch (Throwable able) {
            able.getMessage();
        }
    }

}
           

6,查看生成的.class文件

package com.gupao.designpattern.proxy.self;

import java.lang.reflect.Method;

public class $ProxyO implements SelfProxyInterface {
    SelfInvocationHandler h;

    public $ProxyO(SelfInvocationHandler var1) {
        this.h = var1;
    }

    public void targetMethod() {
        try {
            Method var1 = SelfProxyInterface.class.getMethod("targetMethod", new Class[0]);
            this.h.invoke(this, var1, (Object[])null);
        } catch (Throwable var2) {
            var2.getMessage();
        }

    }
}
           

7,SelfInvocationHandler接口,定义invoke()方法

public interface SelfInvocationHandler {

    public Object invoke(Object proxy, Method method, Object[] args);
}
           

8,SelfJdkProxy,定义newInstance()方法创建代理对象,并实现InvocationHandler接口,重写invoke()方法,通过反射实现方法最终运行

public class SelfJDKProxy implements SelfInvocationHandler{

    private SelfProxyInterface proxyInterface;

    public SelfJDKProxy(SelfProxyInterface proxyInterface) {
        this.proxyInterface = proxyInterface;
    }

    public Object instanceProxy() {
        System.out.println("代理方法开始...");
        SelfProxyInterface instance = (SelfProxyInterface) SelfProxy.newInstance(
                new SelfClassLoader(),
                proxyInterface.getClass().getInterfaces(), this);
        return instance;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        try {
            method.invoke(proxyInterface, args);
            System.out.println("代理方法结束...");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
           

9,客户端执行

public class SelfTest {

    public static void main(String[] args) {
        SelfJDKProxy proxy = new SelfJDKProxy(new SelfJDKProxyTarget());
        SelfProxyInterface proxyInterface = (SelfProxyInterface) proxy.instanceProxy();
        System.out.println(proxyInterface);
        proxyInterface.targetMethod();
    }
}
           
手写JDK动态代理

10,总结

    整个手写动态代理以说明问题为目的,整个流程中所有环境创建都是按照最简单方式在运行,旨在熟悉整个JDK动态代理的执行流程和底层实现;