相关动态
新手如何建设网站/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://fswenzheng.xhstdz.com/news/7637.html 
     栏目首页      相关文章      动态      同类文章      热门文章      网站地图      返回首页 物流园资讯移动站 http://fswenzheng.xhstdz.com/mobile/ , 查看更多   
最新文章
支付宝小程序搜索排名优化,算法规则基础了解
小程序市场可谓是百花齐放,争奇斗艳。小程序搜索排名优化则为小程序获利提供了强大的支持。做优化首先要知道平台的规则&#
解析国内AI写作平台:创新背后的挑战与突破
一、国内 AI 写作平台兴起近年来,随着人工智能技术的飞速发展,国内 AI 写作平台如雨后春笋般涌现。这些平台利用深度学习、自然
解析百度的绿萝算法怎样识别买卖链接
  作为站长,大家都知道,百度于2013年2月20日推出了最新的搜索引擎算法,起名叫绿萝,公告称这个新算法主要是打击买卖链接的
揭秘刷神马SEO排名秘籍,轻松提升网站搜索地位!
深度解析刷神马SEO排名真相与策略,分享实用技巧,助力网站高效提升排名,轻松占领搜索引擎前列!随着互联网的快速发展,SEO(搜
亚马逊运营必备实用工具
常常看见有卖家小伙伴提问利用什么做数据分析、用什么选品等话题。这里强烈建议各位亚马逊卖家以及准备入驻亚马逊卖家的朋友收藏
如何打造一个高效的营销型企业网站,营销型企业网站的核心特点是什么
打造高效营销型企业网站,需关注用户体验、SEO优化、内容质量及数据分析。核心特点为:用户导向、易用性高、转化路径明确。如何
佛山专业SEO优化助力企业电商营销新飞跃
佛山商品SEO优化公司,凭借专业技术和丰富经验,为企业提供全方位互联网营销解决方案。通过精准关键词优化、内容营销、数据分析
ks秒单关注(快速秒单关注,提升用户转化率)
KS秒单关注是一种快速秒单关注的方法,旨在提升用户的转化率。这种方法通过一系列的策略和技巧,能够快速吸引用户的关注,并使他
密码技术应用员理论知识题及答案.docVIP
PAGEPAGE1密码技术应用员理论知识题及答案单选题1.密码系统试运行报告中,记录的每个问题均应具备唯一标识,其作用是()。A、描
外链自动增加:全面解析和战略规划198
引言外链是搜索引擎优化 (SEO) 至关重要的组成部分,可以提高网站在搜索结果页面 (SERP) 中的排名。然而,有时网站可能会经历外
相关文章