【设计模式】代理模式 ( 动态代理 | 模拟 Java 虚拟机生成对应的 代理对象 类 )

简介: 【设计模式】代理模式 ( 动态代理 | 模拟 Java 虚拟机生成对应的 代理对象 类 )

文章目录

前言

一、模拟 JVM 生成对应的 代理对象

二、模拟 JVM 生成对应的 代理对象 完整流程展示

1、目标对象接口

2、被代理对象

3、调用处理程序

4、模拟 JVM 生成的代理对象类

5、客户端

前言

动态代理使用流程 :


① 创建目标对象 : 创建 目标对象 接口 ;


② 创建被代理对象 : 创建 被代理对象 , 实现 目标对象 接口 ;


③ 创建调用处理程序 : 创建 InvocationHandler 子类对象 , 内部持有 被代理对象 , 在 invoke 方法中 , 返回 method.invoke(subject, args) ;


④ 动态创建代理对象 : 调用 Proxy.newProxyInstance 创建 代理对象 实例对象 , 由 JVM 自动创建代理对象类 , 然后再创建对应的实例对象 ;


⑤ 动态代理调用 : 调用 代理对象 实例的相关 目标对象 接口 方法 ;



本篇博客 基于 【设计模式】代理模式 ( 动态代理使用流程 | 创建目标对象 | 创建被代理对象 | 创建调用处理程序 | 动态创建代理对象 | 动态代理调用 ) 三、动态代理使用流程 中的示例 , 模拟写出一个由 Java 虚拟机自动生成的字节码类 ;






一、模拟 JVM 生成对应的 代理对象


下面的类基本 JVM 动态生成的类功能一致 ;


在该动态生成的类中 , 持有 被代理对象 和 调用处理程序 ;


在每个 目标对象 接口方法中 , 使用反射获取对应的方法 , 将


反射获取的 Method 对象实例 ,

持有的 被代理对象实例 ,

方法参数 ,

全部传入 调用处理程序 InvocationHandler 的 invoke 方法中 ;


这也是所有的 目标对象 方法 , 都能在 InvocationHandler 的 invoke 方法中回调到的原因 ;



生成的代码示例 :


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * 代理对象
 *  模拟由 JVM 自动生成的动态代理类
 */
public class DynamicProxy implements Subject {
    /**
     * 代理对象中持有被代理对象的引用
     *  构造方法注入
     */
    private Subject subject;
    /**
     * 持有调用处理程序
     *  构造方法注入
     */
    private InvocationHandler invocationHandler;
    public DynamicProxy(Subject subject, InvocationHandler invocationHandler) {
        this.subject = subject;
        this.invocationHandler = invocationHandler;
    }
    @Override
    public void request() {
        try {
            Method method = subject.getClass().getMethod("request", null);
            invocationHandler.invoke(subject, method, null);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}






二、模拟 JVM 生成对应的 代理对象 完整流程展示



1、目标对象接口


/**
 * 目标接口
 *  代理对象 和 被代理对象 都要实现该接口
 */
public interface Subject {
    void request();
}


2、被代理对象


/**
 * 被代理对象
 */
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("被代理对象 RealSubject request()");
    }
}



3、调用处理程序


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;
    }
}



4、模拟 JVM 生成的代理对象类


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * 代理对象
 *  模拟由 JVM 自动生成的动态代理类
 */
public class DynamicProxy implements Subject {
    /**
     * 代理对象中持有被代理对象的引用
     *  构造方法注入
     */
    private Subject subject;
    /**
     * 持有调用处理程序
     *  构造方法注入
     */
    private InvocationHandler invocationHandler;
    public DynamicProxy(Subject subject, InvocationHandler invocationHandler) {
        this.subject = subject;
        this.invocationHandler = invocationHandler;
    }
    @Override
    public void request() {
        try {
            Method method = subject.getClass().getMethod("request", null);
            invocationHandler.invoke(subject, method, null);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}



5、客户端


import java.lang.reflect.Proxy;
public class Client {
    public static void main(String[] args) {
        // 被代理对象
        Subject realSubject = new RealSubject();
        // 创建调用处理程序 , 内部持有被代理对象
        DynamicInvocationHandler dynamicInvocationHandler =
                new DynamicInvocationHandler(realSubject);
        // 创建动态代理类
        DynamicProxy proxy = new DynamicProxy(realSubject, dynamicInvocationHandler);
        // 动态代理调用
        proxy.request();
    }
}


执行结果 :


image.png


该展示相当于一个静态代理展示 ;


目录
相关文章
|
5天前
|
设计模式 缓存 安全
设计模式——代理模式
静态代理、JDK动态代理、Cglib 代理
设计模式——代理模式
|
21天前
|
虚拟化
vmware虚拟机使用主机代理访问谷歌
vmware虚拟机使用主机代理访问谷歌
|
2月前
|
缓存 Java 测试技术
day27:Java零基础 - 动态代理
【7月更文挑战第27天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
26 2
day27:Java零基础 - 动态代理
|
1月前
|
设计模式 缓存 Java
【十一】设计模式~~~结构型模式~~~代理模式(Java)
文章详细介绍了代理模式(Proxy Pattern),这是一种对象结构型模式,用于给对象提供一个代理以控制对它的访问。文中阐述了代理模式的动机、定义、结构、优点、缺点和适用环境,并探讨了远程代理、虚拟代理、保护代理等不同代理形式。通过一个商务信息查询系统的实例,展示了如何使用代理模式来增加身份验证和日志记录功能,同时保持客户端代码的无差别对待。此外,还讨论了代理模式在分布式技术和Spring AOP中的应用,以及动态代理的概念。
【十一】设计模式~~~结构型模式~~~代理模式(Java)
|
18天前
|
开发者 C# 容器
【独家揭秘】当WPF邂逅DirectX:看这两个技术如何联手打造令人惊艳的高性能图形渲染体验,从环境搭建到代码实践,一步步教你成为图形编程高手
【8月更文挑战第31天】本文通过代码示例详细介绍了如何在WPF应用中集成DirectX以实现高性能图形渲染。首先创建WPF项目并使用SharpDX作为桥梁,然后在XAML中定义承载DirectX内容的容器。接着,通过C#代码初始化DirectX环境,设置渲染逻辑,并在WPF窗口中绘制图形。此方法适用于从简单2D到复杂3D场景的各种图形处理需求,为WPF开发者提供了高性能图形渲染的技术支持和实践指导。
47 0
|
26天前
|
设计模式 Java C++
揭秘!JDK动态代理VS CGLIB:一场关于Java代理界的‘宫心计’,你站哪队?
【8月更文挑战第24天】Java 动态代理是一种设计模式,允许在不改动原类的基础上通过代理类扩展功能。主要实现方式包括 JDK 动态代理和 CGLIB。前者基于接口,利用反射机制在运行时创建代理类;后者采用继承方式并通过字节码技术生成子类实现类的代理。两者在实现机制、性能及适用场景上有明显差异。JDK 动态代理适用于有接口的场景,而 CGLIB 更适合代理未实现接口的类,尽管性能更优但存在一些限制。开发者可根据需求选择合适的代理方式。
68 0
|
1月前
|
设计模式
设计模式的基础问题之代理模式在工作中的问题如何解决
设计模式的基础问题之代理模式在工作中的问题如何解决
|
1月前
|
设计模式 Java API
设计模式-------------静态/动态代理模式(结构型设计模式)
本文详细介绍了代理模式,包括其定义、应用场景、UML类图、代码实现和实际例子,阐述了静态代理和动态代理的区别以及它们的优缺点,展示了如何通过代理模式来控制对目标对象的访问并增强其功能。
|
Java 编译器 安全
Java虚拟机类加载机制
Java虚拟机类加载机制
2149 0