
代理模式结构 : 代理模式中的元素有 客户端 , 主题对象 , 被代理对象 , 代理对象 ;

代理模式的核心 : 代理对象 与 被代理对象 都实现同一个父类或接口 , 这样在客户端使用时 , 客户端 感觉自己与 被代理对象 沟通 , 但用户实际上与 代理对象 进行沟通 ;
静态代理 中 , 代理对象 和 被代理对象 必须实现 主题对象 接口 , 如果 主题对象 接口发生改变 , 则相应的 代理对象 和 被代理对象 都要进行相应修改 ;
动态代理 解决了 静态代理的上述问题 , 不需要手动创建代理对象 , 由 Java 虚拟机实现 代理对象 , 该代理对象自动实现 主题对象 的接口 ;
动态代理执行时 , 动态地创建了字节码文件 , 生成了代理类 ;
动态代理使用流程 :
InvocationHandler 子类对象 , 内部持有 被代理对象 , 在 invoke 方法中 , 返回 method.invoke(subject, args) ;
 Proxy.newProxyInstance 创建 代理对象 实例对象 , 由 JVM 自动创建代理对象类 , 然后再创建对应的实例对象 ;
 /**
 * 目标接口
 *  代理对象 和 被代理对象 都要实现该接口
 */
public interface Subject {
    void request();
}/**
 * 被代理对象
 */
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("被代理对象 RealSubject request()");
    }
}import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicInvocationHandler implements InvocationHandler {
    /**
     * 持有的 被代理对象
     */
    private Subject subject;
    public DynamicInvocationHandler(Subject subject) {
        this.subject = subject;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 调用真实的 被代理对象 的方法
        //  被代理对象的所有的方法的调用都会传到该方法中进行处理
        Object object = method.invoke(subject, args);
        return object;
    }
}import java.lang.reflect.Proxy;
public class Client {
    public static void main(String[] args) {
        // 被代理对象
        Subject realSubject = new RealSubject();
        // 创建调用处理程序 , 内部持有被代理对象
        DynamicInvocationHandler dynamicInvocationHandler =
                new DynamicInvocationHandler(realSubject);
        // 生成动态代理类
        Subject subject = (Subject) Proxy.newProxyInstance(
                realSubject.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(),
                dynamicInvocationHandler);
        // 动态代理调用
        subject.request();
    }
}执行结果 :

动态代理 中的 代理对象对应的 字节码类 是由 Java 虚拟机自动生成的 , 在 java.lang.reflect.Proxy 中 , 调用 ProxyGenerator.generateProxyClass 方法 , 生成了 代理对象 类 , 返回的 byte[] 数据就是字节码类对应的二进制数据 ;
            /*
             * Generate the specified proxy class.
             */
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);ProxyGenerator 的源码需要下载 JDK 源码查看 , 在 IntelliJ IDEA 开发环境中无法查看 ;
网上找到了一篇博客 , 对此描述的很清楚 JDK动态代理[4]----ProxyGenerator生成代理类的字节码文件解析 ;
ProxyGenerator 中的 generateProxyClass 方法中 , 主要调用了 generateClassFile 方法 , 按照 Class 字节码的规范 , 按照顺序依次写入 魔数 , 次版本号 , 主版本号 , 常量池 , 访问修饰符 , 类索引 等数据 ;