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

举报
韩曙亮 发表于 2022/01/12 23:01:05 2022/01/12
【摘要】 文章目录 前言一、模拟 JVM 生成对应的 代理对象二、模拟 JVM 生成对应的 代理对象 完整流程展示1、目标对象接口2、被代理对象3、调用处理程序4、模拟 JVM 生成的代理对象类5、客户端 ...

前言

动态代理使用流程 :

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

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

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

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

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


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





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



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

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

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

  • 反射获取的 Method 对象实例 ,
  • 持有的 被代理对象实例 ,
  • 方法参数 ,

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

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


生成的代码示例 :

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37




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




1、目标对象接口


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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2、被代理对象


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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

执行结果 :

在这里插入图片描述

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

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/120400068

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。