【设计模式】代理模式 ( 动态代理 | 模拟 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


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


目录
相关文章
|
10月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
2621 35
|
10月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
671 8
|
10月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
1097 157
|
10月前
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
944 2
|
10月前
|
存储 Java 索引
用Java语言实现一个自定义的ArrayList类
自定义MyArrayList类模拟Java ArrayList核心功能,支持泛型、动态扩容(1.5倍)、增删改查及越界检查,底层用Object数组实现,适合学习动态数组原理。
415 4
|
10月前
|
IDE JavaScript Java
在Java 11中,如何处理被弃用的类或接口?
在Java 11中,如何处理被弃用的类或接口?
420 5
|
10月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
440 1
|
10月前
|
Java Go 开发工具
【Java】(8)正则表达式的使用与常用类分享
正则表达式定义了字符串的模式。正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
563 1
|
10月前
|
存储 Java 程序员
【Java】(6)全方面带你了解Java里的日期与时间内容,介绍 Calendar、GregorianCalendar、Date类
java.util 包提供了 Date 类来封装当前的日期和时间。Date 类提供两个构造函数来实例化 Date 对象。第一个构造函数使用当前日期和时间来初始化对象。Date( )第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。
367 0
|
10月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
410 1