相关动态
新手如何建设网站/seo上海公司
2024-11-21 11:18

代理模式是一种结构性设计模式,让你能够提供对象的替代品或其占位符。代理控制着对于原对象的访问,并允许在将请求提交给对象前后进行一些处理。

新手如何建设网站/seo上海公司

新手如何建设网站/seo上海公司

  1. 服务接口(ServiceInterface) 声明了服务接口提供的功能。代理必须遵循该接口才能伪装成对象
  2. 服务(Service)类,提供具体的一些实用的业务逻辑
  3. 代理(Proxy)类包含一个指向服务对象的引用成员变量,代理完成其交代的任务(例如延迟加载,记录日志,访问控制或者缓存等)后会将请求传递给服务对象,通常情况下,代理会对其服务对象的整个声明周期进行管理。
  4. 客户端(Client) 能通过同一接口与服务或与代理进行交互,所以你可以在一些需要服务对象的代码中实用代理。
  5. https://www.jianshu.com/p/31a1778ce8b0

我们有一个常用的数据库访问接口,大量的客户端都是对数据库进行直接的访问,对系统资源的消耗特别大,并且有很多的重复查询操作。

新手如何建设网站/seo上海公司

直接访问数据库,可能会非常的慢

这时候我们考虑加入缓存,当需要重复的查询时直接从缓存中获取数据返回到客户端,节省系统开销,并记录一下每一个客户端访问花费的时间。

代理模式建议新建一个与原服务对象接口相同的代理类, 然后更新应用以将代理对象传递给所有原始对象客户端。 代理类接收到客户端请求后会创建实际的服务对象, 并将所有工作委派给它。

新手如何建设网站/seo上海公司

代理将自己伪装成数据库对象,可以在客户端不知道的情况下做缓存查询操作并记录其访问时间或日志

定义查询数据库的接口

 

public interface DataService { // 通过ID查询数据 String getById(Integer id); }

具体的数据库查询业务类

 

public class DataServiceImpl implements DataService{ // 模拟数据 final Map<Integer,String> dataMap = new HashMap<Integer,String>(){{ for (int i = 0; i < 10; i++) { put(i,"data_"+ i); } }}; @Override public String getById(Integer id) { // 模拟数据库查询的耗时 try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } return dataMap.get(id); } }

创建代理类,伪装业务类

 

public class DataServiceProxy implements DataService{ DataService dataService; // 缓存 Map<Integer,String> cacheMap = new HashMap<>(); public DataServiceProxy(DataService dataService) { this.dataService = dataService; } @Override public String getById(Integer id) { // 记录访问的开始时间 final long start = System.currentTimeMillis(); String result = null; // 优先从缓存获取 String cache = getCache(id); if (cache == null){ result = dataService.getById(id); // 放入缓存中 putCache(id,result); }else { result = cache; } final long end = System.currentTimeMillis(); System.out.println("耗时" + (end - start) + "ms"); return result; } // 缓存信息 private void putCache(Integer id,String value){ cacheMap.put(id,value); } // 获取缓存信息 private String getCache(Integer id){ return cacheMap.get(id); } }

客户端

 

@Test public void ProxyTest() { DataService dataService = new DataServiceImpl(); DataServiceProxy dataServiceProxy = new DataServiceProxy(dataService); dataServiceProxy.getById(1); // 第二次查询 dataServiceProxy.getById(1); dataServiceProxy.getById(1); }

这种代理模式的设计方式,我们一般称之为静态代理:由编码人员创建完成或由特定工具生成源代码,在编译时就已经将接口、被代理类、代理类等确定类下来,在程序运行之前,代理类的字节码文件已经生成了。如果由其他的代理内容,可能需要新建很多的代码来实现。

与静态代理最大的区别在于,动态代理类是在程序运行时创建的代理。例如在上面的例子中代理类是我们自己定义的,在程序运行之前就已经编译完成。在动态代理中,代理类不是在代码中定义,而是在程序运行时根据我们的需要在代码中动态生成的。

在中我们提到动态代理,一般绕不开动态代理和动态代理。

利用自带的代理类来完成,相当于利用一个拦截器(需实现接口)配合反射机制生成一个实现代理类的匿名接口,在调用具体的方法前调用来处理。

我们依旧使用接口和业务类来完成一个动态代理的案例。

  1. 创建被代理类的接口和业务类(已经有了
  2. 创建接口的实现类,在方法中实现代理的逻辑
  3. 通过的静态方法创建一个代理对象。
 

public class JDKProxy implements InvocationHandler { // 被代理对象 private Object object; // 缓存 Map<Integer,String> cacheMap = new HashMap<>(); public JDKProxy(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 只代理其中的查询方法 if (method.getName().equals("getById")){ // 参数 Integer id = (Integer) args[0]; // 记录访问的开始时间 final long start = System.currentTimeMillis(); String result = null; // 优先从缓存获取 String cache = getCache(id); if (cache == null){ // 代理执行 result =(String) method.invoke(object,args); // 放入缓存中 putCache(id,result); }else { result = cache; } final long end = System.currentTimeMillis(); System.out.println("耗时" + (end - start) + "ms"); return result; }else { return method.invoke(object,args); } } // 缓存信息 private void putCache(Integer id,String value){ cacheMap.put(id,value); } // 获取缓存信息 private String getCache(Integer id){ return cacheMap.get(id); } }

接口是代理实例的调用处理程序实现的一个接口,每一个代理实例都有一个关联的调用处理程序;在代理实例调用方法()时,方法调用被编码分派到调用处理程序的方法。

每一个动态代理类的调用处理程序都必须实现接口,并且每个代理类的实例都关联到了实现该接口的动态代理类调用处理程序中,当我们通过动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现接口类的方法来调用,看如下方法

 

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

客户端在调用时的方式也和静态代理不一样,最终是使用代理类来进行方法的调用

 

@Test public void JDKProxyTest() { DataService dataService = new DataServiceImpl(); JDKProxy jdkProxy = new JDKProxy(dataService); // 获取代理对象 DataService dataServiceProxy = (DataService) Proxy.newProxyInstance(DataService.class.getClassLoader(), new Class[]{DataService.class}, jdkProxy); dataServiceProxy.getById(1); dataServiceProxy.getById(1); }

其运行的结果是一样的,都完成了代理内容。

类就是用来创建一个代理对象的类,它提供了很多方法,我们最常用的是方法。

 

public static Object newProxyInstance(ClassLoader loader,                                              Class<?>[] interfaces,                                              InvocationHandler h)

就是创建一个代理类对象,它接收三个参数

  • :指定代理类的类加载器(我们传入当前测试类的类加载器
  • :一个对象数组,代理类需要实现的接口(我们传入被代理类实现的接口,这样生成的代理类和被代理类就实现了相同的接口
  • :一个对象,表示的是当动态代理对象调用方法的时候会关联到哪一个对象上,用来处理方法的调用。这里传入我们自己实现的

利用开源包,对代理对象类的文件加载进来,通过修改其字节码生成子类来处理。

  1. 导入包,这里包含了和
  2. 创建接口的实现类,在方法中实现代理的逻辑
  3. 编写方法(自定义)返回代理类对象
 

<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>

 

public class CglibProxy implements MethodInterceptor { // 被代理对象,便于通用,可以写成Object private Object object; // 缓存 Map<Integer,String> cacheMap = new HashMap<>(); @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { // 只代理其中的查询方法 if (method.getName().equals("getById")) { // 参数 Integer id = (Integer) args[0]; // 记录访问的开始时间 final long start = System.currentTimeMillis(); String result = null; // 优先从缓存获取 String cache = getCache(id); if (cache == null) { result = (String)method.invoke(object,args); // 放入缓存中 putCache(id, result); } else { result = cache; } final long end = System.currentTimeMillis(); System.out.println("耗时" + (end - start) + "ms"); return result; } else { return method.invoke(object, args); } } // 获取代理对象 这里采用了范型的写法,更直观的传入被代理类,然后返回代理对象 public <T> T getCglibProxy(T t){ this.object = t;//为目标对象target赋值 Enhancer enhancer = new Enhancer(); //设置父类,因为Cglib是针对指定的类生成一个子类,所以需要指定父类 enhancer.setSuperclass(object.getClass()); //设置回调 enhancer.setCallback(this); //创建并返回代理对象 Object result = enhancer.create(); return (T) result; } // 缓存信息 private void putCache(Integer id,String value){ cacheMap.put(id,value); } // 获取缓存信息 private String getCache(Integer id){ return cacheMap.get(id); } }

 

@Test public void CGLBProxyTest(){ // 被代理类 这里可以不用接口声明哦 DataService dataService = new DataServiceImpl(); CglibProxy cglibProxy = new CglibProxy(); // 获取代理对象 DataService proxy = cglibProxy.getCglibProxy(dataService); proxy.getById(1); proxy.getById(1); }

    以上就是本篇文章【新手如何建设网站/seo上海公司】的全部内容了,欢迎阅览 ! 文章地址:http://sjzytwl.xhstdz.com/news/7637.html 
     栏目首页      相关文章      动态      同类文章      热门文章      网站地图      返回首页 物流园资讯移动站 http://sjzytwl.xhstdz.com/mobile/ , 查看更多   
最新文章
苹果手机怎么恢复备份?详细攻略为你整理好了!云备份怎么恢复到手机「苹果手机怎么恢复备份?详细攻略为你整理好了!」
随着智能手机和互联网的普及,手机中存储的个人信息、照片、视频、聊天记录等数据会变得越来越多。一旦手机丢失、损坏或系统出现
李亚鹏正式息影 投资50亿丽江当老板金立手机老板「李亚鹏正式息影 投资50亿丽江当老板」
  华西都市报4月28日讯 昨日,李亚鹏打造的“云南省文化产业试验园”项目北京签约“我每年只选一部戏来拍,这已经严格遵循了10
怎样采用比特币挖矿?手机挖矿「怎样采用比特币挖矿?」
好吧,废话不多说了,其实比特币 - Bitcoin 出现时间已经很久了,不过对于新手来说,还是需要讲解一下的。关于比特币。FORECE 在
定了!苹果 2022 秋季发布会定档,9月8日见iPhone 14 来了?苹果手机发布会「定了!苹果 2022 秋季发布会定档,9月8日见iPhone 14 来了?」
又是九月,丰收的季节,今年的苹果又该熟了.......正如此前传闻那样,今晚苹果正式向外界发送了邀请函,宣布将于当地时间 9月7日
苹果手机微信闪退怎么回事苹果手机闪退是什么原因「苹果手机微信闪退怎么回事」
  品牌型号:iPhone12  系统版本:IOS14  苹果手机如果出现微信闪退的状况,首先我们得寻找原因,接下来小编就带着你们来
ZArchiver手机解压缩工具chm文件手机怎么打开「ZArchiver手机解压缩工具」
ZArchiver是一款功能强大的解压缩工具APP,可用于解压文件或压缩文件,软件支持多种文件格式的压缩和解压缩,包括ZIP、RAR、7Z、
【原】一部手机最长能用几年?主要有三个因素,决定了手机的寿命什么手机寿命最长「【原】一部手机最长能用几年?主要有三个因素,决定了手机的寿命」
一部手机最长能用几年?主要取决于以下这几个重要因素,才能决定手机的使用寿命。在当今社会,智能手机已经成为我们生活中不可或
iQOO 3评测:旗舰机还能在哪提升?这部手机给了答案机械手机「iQOO 3评测:旗舰机还能在哪提升?这部手机给了答案」
  文/晓光 于泽 瑞豪 视频/贾乾 图/苏航  从去年成立至今,iQOO这品牌发布了不到十款产品,并成功在互联网渠道占据了自己的
2013-4-7发布华为模拟器eNSP月度更新版(V2.0)支持全系列AR路由器模拟华为手机模拟器「2013-4-7发布华为模拟器eNSP月度更新版(V2.0)支持全系列AR路由器模拟」
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.ne
ADB驱动源码深度解析,从原理探究到实践应用android手机驱动「ADB驱动源码深度解析,从原理探究到实践应用」
摘要:,,本文深入解析ADB(Android Debug Bridge)驱动源码,从原理到实践全面阐述。文章首先介绍了ADB的基本原理和主要功能,
相关文章