相关动态
新手如何建设网站/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://tiush.xhstdz.com/news/7637.html 
     栏目首页      相关文章      动态      同类文章      热门文章      网站地图      返回首页 物流园资讯移动站 http://tiush.xhstdz.com/mobile/ , 查看更多   
最新文章
国际站:SEO Checker诊断工具助力商家诊断详情页,提升seo效果
国际站商家看过来:众所周知,一个优质的商品描述,可以提升买家转化的同时,还可以带来更多免费流量,从而让商家获得更多询盘和
【富蕴网站优化】在网站优化中有哪些常用的网站推广方式?
1、,百度,google的优化,针对,音乐,mp3下载,电影、游戏等一级,二级,甚至关键字优化。Seo介绍的网站很多,就不在这里重复
公众号简单爬虫--把公众号文章全部转载到网站(二)
根据上一篇的方法,我们得到了一个获取列表信息的地址,而且是用get方法就可以的地址.那么事情就变得很简单了,就是常规的爬取信息
1.【typecho】个人博客安装—使用群晖演示
哈喽,大家好今天给大家带来的是最近在群晖上安装一个博客的演示。先给大家看一下安装好之后的效果。虽然说现在使用博客和看博客
SEO优化攻略,揭秘网站排名提升与流量最大化技巧
本文深入解析SEO优化策略,通过关键词研究、高质量内容创作、链接建设等技术手段,帮助提升网站在搜索引擎中的排名,从而实现流
【HMNOTE搜狗手机输入法下载】小米HMNOTE搜狗手机输入法12.1.1免费下载
搜狗输入法,拥有超大中文词库,输入更加精准,智能。搜狗智能旺仔带你用表达,斗图,妙语,输入更加有趣。******特色功能******
vivo S19 Pro:全焦段人像拍照的5G游戏续航新宠
在智能手机市场日益同质化的今天,vivo S19 Pro以其独特的全焦段人像拍照功能、强大的5G性能以及出色的游戏续航能力,成为了众多
12月12日,星期四, 每天60秒读懂全世界!
新闻来源:百度热搜榜1. 25年老员工被开除 法院判赔98万近日,工作25年的李某被安排学习员工手册,全程玩手机遭公司开除,引发热
刚子扯谈:网站运营在左 技术在右 真TM扯
2013年8月5日,雨未下,天猴焖开片语:今天的扯谈内容是我转载我Java学习交流群里面一个哥们,当然我推荐他加入了朋友的网络分析
做seo营销网站/百度惠生活商家入驻
假定我们定义了一个Persion的message type,我们的用法可能如下定义 和 package tutorial;message Person {required int
相关文章