广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java的代理模式你真的了解吗
  • 739
分享到

Java的代理模式你真的了解吗

Java代理Java代理模式 2022-11-13 05:11:55 739人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录代理模式原理解析动态代理的原理解析代理模式的应用场景代理模式原理解析 代理模式(Proxy Design Pattern),它在不改变原始类(或者叫被代理类)代码的情况下,通过引

代理模式原理解析

代理模式(Proxy Design Pattern),它在不改变原始类(或者叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能。

public class UserController {
  //...省略其他属性和方法...
  private MetricsCollector metricsCollector; // 依赖注入

  public UserVo login(String telephone, String passWord) {
    long startTimestamp = System.currentTimeMillis();

    // ... 省略login逻辑...

    long endTimeStamp = System.currentTimeMillis();
    long responseTime = endTimeStamp - startTimestamp;
    RequestInfo requestInfo = new RequestInfo("login", responseTime, startTimestamp);
    metricsCollector.recordRequest(requestInfo);

    //...返回UserVo数据...
  }

  public UserVo reGISter(String telephone, String password) {
    long startTimestamp = System.currentTimeMillis();

    // ... 省略register逻辑...

    long endTimeStamp = System.currentTimeMillis();
    long responseTime = endTimeStamp - startTimestamp;
    RequestInfo requestInfo = new RequestInfo("register", responseTime, startTimestamp);
    metricsCollector.recordRequest(requestInfo);

    //...返回UserVo数据...
  }
}

上面代码有两个问题,第一,性能计数器框架代码侵入到业务代码中,跟业务高度耦合。如果需要替换这个框架,成本比较大。第二,收集接口请求的代码跟业务代码无关,不应该放到一个类中。业务类最好职责更加单一,只负责业务处理。
现在改成代理模式:

public interface IUserController {
  UserVo login(String telephone, String password);
  UserVo register(String telephone, String password);
}

public class UserController implements IUserController {
  //...省略其他属性和方法...

  @Override
  public UserVo login(String telephone, String password) {
    //...省略login逻辑...
    //...返回UserVo数据...
  }

  @Override
  public UserVo register(String telephone, String password) {
    //...省略register逻辑...
    //...返回UserVo数据...
  }
}

public class UserControllerProxy implements IUserController {
  private MetricsCollector metricsCollector;
  private UserController userController;

  public UserControllerProxy(UserController userController) {
    this.userController = userController;
    this.metricsCollector = new MetricsCollector();
  }

  @Override
  public UserVo login(String telephone, String password) {
    long startTimestamp = System.currentTimeMillis();

    // 委托
    UserVo userVo = userController.login(telephone, password);

    long endTimeStamp = System.currentTimeMillis();
    long responseTime = endTimeStamp - startTimestamp;
    RequestInfo requestInfo = new RequestInfo("login", responseTime, startTimestamp);
    metricsCollector.recordRequest(requestInfo);

    return userVo;
  }

  @Override
  public UserVo register(String telephone, String password) {
    long startTimestamp = System.currentTimeMillis();

    UserVo userVo = userController.register(telephone, password);

    long endTimeStamp = System.currentTimeMillis();
    long responseTime = endTimeStamp - startTimestamp;
    RequestInfo requestInfo = new RequestInfo("register", responseTime, startTimestamp);
    metricsCollector.recordRequest(requestInfo);

    return userVo;
  }
}

//UserControllerProxy使用举例
//因为原始类和代理类实现相同的接口,是基于接口而非实现编程
//将UserController类对象替换为UserControllerProxy类对象,不需要改动太多代码

IUserController userController = new UserControllerProxy(new UserController());

按照基于接口而非实现编程的设计思想,将原始类对象替换为代理类对象的时候,刚刚的代理模式代码实现中,代理类和原始类需要实现相同的接口。但是如果原始类没有定义接口,并且原始类代码并不是我们开发维护的,也不能重新定义一个接口,这种情况下,如何实现代理模式呢?
对于这种外部类的扩展,一般都采用继承的方式。让代理类继承原始类,然后扩展附加功能。代码如下:

public class UserControllerProxy extends UserController {
  private MetricsCollector metricsCollector;

  public UserControllerProxy() {
    this.metricsCollector = new MetricsCollector();
  }

  public UserVo login(String telephone, String password) {
    long startTimestamp = System.currentTimeMillis();

    UserVo userVo = super.login(telephone, password);

    long endTimeStamp = System.currentTimeMillis();
    long responseTime = endTimeStamp - startTimestamp;
    RequestInfo requestInfo = new RequestInfo("login", responseTime, startTimestamp);
    metricsCollector.recordRequest(requestInfo);

    return userVo;
  }

  public UserVo register(String telephone, String password) {
    long startTimestamp = System.currentTimeMillis();

    UserVo userVo = super.register(telephone, password);

    long endTimeStamp = System.currentTimeMillis();
    long responseTime = endTimeStamp - startTimestamp;
    RequestInfo requestInfo = new RequestInfo("register", responseTime, startTimestamp);
    metricsCollector.recordRequest(requestInfo);

    return userVo;
  }
}

//UserControllerProxy使用举例
UserController userController = new UserControllerProxy();

动态代理的原理解析

另外,刚刚的代码实现还是有点问题。一方面,我们需要在代理类中,将原始类中的所有方法,都要重新实现一遍,而且为每个方法都附加相似的代码逻辑。另一方面,如果要添加功能的类不止有一个,我们需要针对每个类都创建一个代理类。
如果有50个要添加附加功能的原始类,那我们就要创建50个对应的代理类,导致项目中的类个数成倍增加,提高维护成本。而且每个代理类的代码都有点重复,增加开发成本,这种问题该如何解决?

可以使用动态代理(Dynamic Proxy),Java动态代理实现。

public class MetricsCollectorProxy {
  private MetricsCollector metricsCollector;

  public MetricsCollectorProxy() {
    this.metricsCollector = new MetricsCollector();
  }

  public Object createProxy(Object proxiedObject) {
    Class<?>[] interfaces = proxiedObject.getClass().getInterfaces();
    DynamicProxyHandler handler = new DynamicProxyHandler(proxiedObject);
    return Proxy.newProxyInstance(proxiedObject.getClass().getClassLoader(), interfaces, handler);
  }

  private class DynamicProxyHandler implements InvocationHandler {
    private Object proxiedObject;

    public DynamicProxyHandler(Object proxiedObject) {
      this.proxiedObject = proxiedObject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      long startTimestamp = System.currentTimeMillis();
      Object result = method.invoke(proxiedObject, args);
      long endTimeStamp = System.currentTimeMillis();
      long responseTime = endTimeStamp - startTimestamp;
      String apiName = proxiedObject.getClass().getName() + ":" + method.getName();
      RequestInfo requestInfo = new RequestInfo(apiName, responseTime, startTimestamp);
      metricsCollector.recordRequest(requestInfo);
      return result;
    }
  }
}

//MetricsCollectorProxy使用举例
MetricsCollectorProxy proxy = new MetricsCollectorProxy();
IUserController userController = (IUserController) proxy.createProxy(new UserController());

代理模式的应用场景

代理模式的应用场景非常多,下面举例说一些比较常见的用法。

  • 业务系统的非功能性需求开发

比如在业务系统中的一些非功能性需求,监控、统计、鉴权、限流、事物、幂等、日志。这些附加功能与业务系统功能解耦,放到代理类中统一处理,让程序员只需要关注业务开发。

  • 代理模式在PRC、缓存中的应用

实际上,rpc框架也可以看作一种代理模式,GoF的设计模式一书中把它称作远程代理,通过远程代理,将网络通信、数据编码解码等细节隐藏起来。客户端在使用RPC服务的时候,就像使用本地函数一样,无需了解跟服务器交互的细节。

代理在缓存中的应用,假设要开发一个接口请求的缓存功能,对于某些接口请求,输入参数相同,在设定的过期时间内,直接返回缓存结果,不用重新进行逻辑业务处理

到此这篇关于Java的代理模式你真的了解吗的文章就介绍到这了,更多相关Java代理模式内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java的代理模式你真的了解吗

本文链接: https://www.lsjlt.com/news/144284.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java的代理模式你真的了解吗
    目录代理模式原理解析动态代理的原理解析代理模式的应用场景代理模式原理解析 代理模式(Proxy Design Pattern),它在不改变原始类(或者叫被代理类)代码的情况下,通过引...
    99+
    2022-11-13
    Java代理 Java代理模式
  • java的泛型你真的了解吗
    目录泛型的概述和优势自定义泛型类自定义泛型方法自定义泛型接口泛型通配符、上下限总结泛型的概述和优势 泛型概述 泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检...
    99+
    2022-11-13
    java泛型
  • 关于Java Object你真的了解了吗
    导读: 在平时的coding中hashCode()和equals()的使用的场景有哪些?clone深复制怎么实现?wait()和notify()有什么作用?finalize()方法干嘛的?看似coding中使用的不多,不重要,但是有没有跟我...
    99+
    2023-05-31
    java object ava
  • Java 动态代理你真的懂了吗(动态和代理)
    好几天不写文章,今天来写一篇,从之前的计划表上看到还有关于java的动态代理没写,这个技术平常用的少,也不是特别好理解,今天补上这篇,希望能讲明白,不至于像我一样迷茫好久,开始吧 动...
    99+
    2022-11-12
    Java 动态代理 java代理模式
  • Java 缓存:你真的了解它吗?
    在 Java 开发中,缓存是一个非常重要的概念。它可以大大提升应用程序的性能,减少对底层资源的占用,提高用户体验。但是,你真的了解 Java 缓存吗?本文将为大家介绍 Java 缓存的基本概念、分类、应用场景以及常见的缓存框架。 一、缓存...
    99+
    2023-10-06
    缓存 学习笔记 面试
  • 你真的了解 Java 分布式编程算法吗?
    Java分布式编程算法是一种处理分布式计算的技术,它可以通过不同的节点分布计算任务,将计算结果整合在一起。在本文中,我们将深入了解Java分布式编程算法,并提供一些示例代码来帮助您更好地理解。 Java分布式编程算法的基础概念 Java分布...
    99+
    2023-06-20
    教程 分布式 编程算法
  • Java递归寻路实现,你真的理解了吗
    目录引使用递归计算阶乘地图创建核心完整代码总结引 看懂这张图,方法调用方法,栈开新栈,递归尾结束要回到main栈,必须一级一级返回,每一次返回都是调用整个方法,调用完成栈被释放,直至回到栈底main递归结束并能够自己画出来,理解递归的运行...
    99+
    2017-05-23
    Java递归 java实现
  • Java和JavaScript的异同,你真的了解吗?
    Java和JavaScript是两种非常常见的编程语言,它们在很多方面有着相似的特性,但它们也有着很多不同之处。在本文中,我们将探讨Java和JavaScript的异同,并且演示一些代码示例来帮助你更好地理解它们。 Java和JavaS...
    99+
    2023-10-24
    javascript http 重定向
  • JAVA设计模式中的策略模式你了解吗
    目录策略模式策略模式是什么策略模式的使用场景策略模式实践总结策略模式 世界上本没有模式; 一些程序老鸟在长时间的编程工作总结出高效的代码写法被后世推崇; 并整理出固定的写法规范,这个...
    99+
    2022-11-13
    JAVA设计模式 JAVA策略模式
  • 你真的理解Java中的ArrayList吗
    目录1. 为什么需要ArrayList?2. ArrayList底层是如何实现的?3. 结合源码分析主要成员变量4. 个人的一点总结1. 为什么需要ArrayList? 图1...
    99+
    2022-11-12
    java中arraylist的用法 java定义一个arraylist列表 java中arraylist排序
  • ASP分布式架构,你真的了解吗?
    ASP(Active Server Pages)是一种动态网页开发技术,它允许开发人员使用服务器端脚本语言生成动态内容。ASP分布式架构是在ASP技术的基础上,通过分布式技术实现的一种多节点协作的架构。在本文中,我们将深入探讨ASP分布式架...
    99+
    2023-06-14
    分布式 面试 函数
  • Python 缓存分布式,你真的了解吗?
    在软件开发中,缓存是提高系统性能的重要手段之一。在 Python 中,我们可以使用第三方库来实现缓存功能,例如:redis、memcached、pycache、dogpile.cache 等等。而缓存分布式则是将缓存数据分布在多台机器上,...
    99+
    2023-07-26
    缓存 分布式 学习笔记
  • JAVA设计模式---原型模式你了解吗
    目录介绍角色Java语言提供的clone()方法代码演示—克隆羊结论深浅拷贝深浅拷贝探讨实现深克隆的方式一 : 手动对引用对象进行克隆实现深克隆的方式二 :序列化原型模式对单例模式的...
    99+
    2022-11-12
    JAVA设计模式 JAVA原型模式
  • C++中的函数你真的理解了吗
    目录1 概述2 函数的定义及调用3 值传递4 函数的常见形式5 函数的声明6 函数的分文件编写作用:让代码结构更加清晰1.2.3.4.总结1 概述 作用:将一段经常使用的代码进行封装...
    99+
    2022-11-13
    理解C++ C++函数
  • C++中的数组你真的理解了吗
    目录1 概述2 一维数组2.1 一维数组定义方式2.2 一维数组组名2.3 冒泡排序3 二维数组3.1 二维数组定义方式3.2 二维数组数组名3.3二维数组应用举例总结1 概述 所谓...
    99+
    2022-11-13
    理解C++ C++数组
  • 你真的了解Java的多线程方法吗
    目录Java 多线程方法详解startrunyieldjoinsleepInterruptdeamonPriority总结Java 多线程方法详解 start start方法&nbs...
    99+
    2022-11-13
    Java多线程 多线程方法
  • Java分布式开发必备框架,你真的了解吗?
    随着互联网技术的发展,越来越多的企业开始采用分布式架构来构建应用程序,以满足高并发、高可靠、高性能等需求。而在Java分布式开发中,一些框架被广泛使用,本文将介绍几个必备框架,帮助你更好地理解和应用分布式开发。 Spring Cloud...
    99+
    2023-09-30
    分布式 windows 框架
  • 你真的了解IP地址吗?
    本文已收录于专栏 ⭐️ 《计算机网络》⭐️ 学习指南: IP协议基本认识分类地址多播地址 无分类地址划分方式子网掩码 IP 分片与重组IPv6基本认识IPv4 首部与 ...
    99+
    2023-09-09
    tcp/ip 网络 服务器 网络协议 ip
  • 你真的需要了解Bash吗?
    Bash是一种强大的命令行解释器,它是Linux和macOS操作系统上的默认Shell。尽管它是如此重要,但很多人并不了解Bash的实际用途。在本文中,我们将探讨Bash的重要性以及它如何帮助我们更好地管理和控制计算机系统。 Bash是什么...
    99+
    2023-08-15
    path bash http
  • ASP 框架教程:你真的理解了吗?
    ASP框架教程:你真的理解了吗? ASP框架是一个非常流行的Web应用程序开发框架,使用了Microsoft ASP.NET技术。这个框架的目的是为了让开发人员更快速、更容易地创建Web应用程序。但是,ASP框架的概念并不容易理解,因此在这...
    99+
    2023-08-05
    框架 教程 学习笔记
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作