Java为什么要用代理,java如何实现代理机制

  Java为什么要用代理,java如何实现代理机制

  

目录

代理模式原理解析动态代理的原理解析代理模式的应用场景

 

  

代理模式原理解析

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

 

  公共类用户控制器{ //.省略其他属性和方法.私有公制收集器公制收集器;//依赖注入公共用户登录(字符串电话,字符串密码){长起始时间戳=系统。当前时间毫秒();//.省略注册逻辑.长结束时间戳=系统。当前时间毫秒();长响应时间=结束时间戳-开始时间戳;request info request info=新的请求信息(登录,响应时间,开始时间戳);度量收集器。记录请求(请求信息);//.返回用户沃数据.}公共用户VO注册(字符串电话,字符串密码){长起始时间戳=系统。当前时间毫秒();//.省略注册逻辑.长结束时间戳=系统。当前时间毫秒();长响应时间=结束时间戳-开始时间戳;request info request info=新的请求信息( register ,responseTime,start timestamp);度量收集器。记录请求(请求信息);//.返回用户沃数据.}}上面代码有两个问题,第一,性能计数器框架代码侵入到业务代码中,跟业务高度耦合。如果需要替换这个框架,成本比较大。第二,收集接口请求的代码跟业务代码无关,不应该放到一个类中。业务类最好职责更加单一,只负责业务处理。现在改成代理模式:

  公共接口IUserController { UserVo登录(字符串电话,字符串密码);用户沃注册(字符串电话,字符串密码);}公共类用户控制器实现IUserController { //.省略其他属性和方法.@覆盖公共UserVo登录(字符串电话,字符串密码){ //.省略注册逻辑.//.返回用户沃数据.} @覆盖公共UserVo寄存器(字符串电话,字符串密码){ //.省略注册逻辑.//.返回用户沃数据.} }公共类用户控制代理实现iuser控制器{私有度量收集器度量收集器;私有user controller userControllerpublic user controller proxy(用户控制器用户控制器){ this。用户控制器=用户控制器;这个。度量收集器=新度量收集器();} @ Override公共用户VO登录(字符串电话,字符串密码){长起始时间戳=系统。当前时间毫秒();//委托用户VO用户VO=用户控制器。登录(电话,密码);长结束时间戳=系统。当前时间毫秒();长时间响应

  nseTime = 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代理模式内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • java从文件中读取数据的六种方法是什么,java如何从文件中读取数据
  • java从文件中读取数据的六种方法是什么,java如何从文件中读取数据,java从文件中读取数据的六种方法
  • java 获取当前时间的三种方法是什么,java如何获取当前的时间
  • java 获取当前时间的三种方法是什么,java如何获取当前的时间,java 获取当前时间的三种方法
  • java 实体转map,实体对象转map,Java如何实现实体类转Map、Map转实体类
  • ,,Java如何基于wsimport调用wcf接口
  • javaarraylist用法,java如何遍历arraylist
  • java如何将两个数组合并为一个数组,合并数组算法
  • java如何编写函数,Java方法怎么写
  • java定位系统怎么做,java如何定位线上问题
  • Java如何打包为apk,java如何打包jar包_1
  • 如何判断char是不是空格,java如何判断字符是不是空格
  • java面向对象菜鸟教程,java如何面向对象
  • java如何换行输入,java输出语句中怎么换行
  • 顺时针打印二维数组java,java如何输出一个二维数组
  • 留言与评论(共有 条评论)
       
    验证码: