推广 热搜: 行业  设备    系统  参数  经纪    教师  机械  中国 

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

   日期:2024-11-21     作者:xasic    caijiyuan   评论:0    移动:http://yejunbin01.xhstdz.com/mobile/news/7637.html
核心提示:代理模式是一种结构性设计模式,让你能够提供对象的替代品或其占位符。代理控制着对于原对象的访问,并允许在将请求

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

新手如何建设网站/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); }

本文地址:http://yejunbin01.xhstdz.com/news/7637.html    物流园资讯网 http://yejunbin01.xhstdz.com/ , 查看更多

特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。

 
 
更多>同类最新文章
0相关评论

文章列表
相关文章
最新动态
推荐图文
最新文章
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号