什么是代理模式?

       代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。

举个例子来说明:假如说我现在想买一辆二手车,虽然我可以自己去找车源,做质量检测等一系列的车辆过户流程,但是这确实太浪费我得时间和精力了。我只是想买一辆车而已为什么我还要额外做这么多事呢?于是我就通过中介公司来买车,他们来给我找车源,帮我办理车辆过户流程,我只是负责选择自己喜欢的车,然后付钱就可以了。用图表示如下:

为什么要用代理模式?

  • 中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
  • 开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。

有哪几种代理模式?

我们有多种不同的方式来实现代理。如果按照代理创建的时期来进行分类的话, 可以分为两种:静态代理、动态代理。静态代理是由程序员创建或特定工具自动生成源代码,在对其编译。在程序员运行之前,代理类.class文件就已经被创建了。动态代理是在程序运行时通过反射机制动态创建的。

1.静态代理     

 一步:创建服务类接口

 1 package main.java.proxy;
 2
 3 /**  4  * @Auther: dan gao  5  * @Description:  6  * @Date: 22:40 2018/1/9 0009  7 */  8 public interface BuyHouse {  9 void buyHosue(); 10 }

第二步:实现服务接口

 1 import main.java.proxy.BuyHouse;
 2
 3 /**  4  * @Auther: dan gao  5  * @Description:  6  * @Date: 22:42 2018/1/9 0009  7 */  8 public class BuyHouseImpl implements BuyHouse {  9 10  @Override 11 public void buyHosue() { 12 System.out.println("我要买房"); 13  } 14 }

第三步:创建代理类

 1 package main.java.proxy.impl;
 2
 3 import main.java.proxy.BuyHouse;  4  5 /**  6  * @Auther: dan gao  7  * @Description:  8  * @Date: 22:43 2018/1/9 0009  9 */ 10 public class BuyHouseProxy implements BuyHouse { 11 12 private BuyHouse buyHouse; 13 14 public BuyHouseProxy(final BuyHouse buyHouse) { 15 this.buyHouse = buyHouse; 16  } 17 18  @Override 19 public void buyHosue() { 20 System.out.println("买房前准备"); 21  buyHouse.buyHosue(); 22 System.out.println("买房后装修"); 23 24  } 25 }

第四步:编写测试类

import main.java.proxy.impl.BuyHouseImpl;
import main.java.proxy.impl.BuyHouseProxy;/** * @Auther: dan gao * @Description: * @Date: 22:43 2018/1/9 0009 */ public class ProxyTest { public static void main(String[] args) { BuyHouse buyHouse = new BuyHouseImpl(); buyHouse.buyHosue(); BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse); buyHouseProxy.buyHosue(); } }

静态代理总结:

优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展。

缺点:我们得为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。                                             

2.动态代理

  在动态代理中我们不再需要再手动的创建代理类,我们只需要编写一个动态处理器就可以了。真正的代理对象由JDK再运行时为我们动态的来创建。

第一步:编写动态处理器

 1 package main.java.proxy.impl;
 2
 3 import java.lang.reflect.InvocationHandler;  4 import java.lang.reflect.Method;  5  6 /**  7  * @Auther: dan gao  8  * @Description:  9  * @Date: 20:34 2018/1/12 0012 10 */ 11 public class DynamicProxyHandler implements InvocationHandler { 12 13 private Object object; 14 15 public DynamicProxyHandler(final Object object) { 16 this.object = object; 17  } 18 19  @Override 20 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 21 System.out.println("买房前准备"); 22 Object result = method.invoke(object, args); 23 System.out.println("买房后装修"); 24 return result; 25  } 26 }

第二步:编写测试类

 1 package main.java.proxy.test;
 2
 3 import main.java.proxy.BuyHouse;  4 import main.java.proxy.impl.BuyHouseImpl;  5 import main.java.proxy.impl.DynamicProxyHandler;  6  7 import java.lang.reflect.Proxy;  8  9 /** 10  * @Auther: dan gao 11  * @Description: 12  * @Date: 20:38 2018/1/12 0012 13 */ 14 public class DynamicProxyTest { 15 public static void main(String[] args) { 16 BuyHouse buyHouse = new BuyHouseImpl(); 17 BuyHouse proxyBuyHouse = (BuyHouse) Proxy.newProxyInstance(BuyHouse.class.getClassLoader(), new 18 Class[]{BuyHouse.class}, new DynamicProxyHandler(buyHouse)); 19  proxyBuyHouse.buyHosue(); 20  } 21 }

注意ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法是固定的

  • Class<?>[] interfaces:指定目标对象实现的接口的类型,使用泛型方式确认类型
  • InvocationHandler:指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法

动态代理总结:虽然相对于静态代理,动态代理大大减少了我们的开发任务,同时减少了对业务接口的依赖,降低了耦合度。但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持interface代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫Proxy。Java的继承机制注定了这些动态代理类们无法实现对class的动态代理,原因是多继承在Java中本质上就行不通。有很多条理由,人们可以否定对 class代理的必要性,但是同样有一些理由,相信支持class动态代理会更美好。接口和类的划分,本就不是很明显,只是到了Java中才变得如此的细化。如果只从方法的声明及是否被定义来考量,有一种两者的混合体,它的名字叫抽象类。实现对抽象类的动态代理,相信也有其内在的价值。此外,还有一些历史遗留的类,它们将因为没有实现任何接口而从此与动态代理永世无缘。如此种种,不得不说是一个小小的遗憾。但是,不完美并不等于不伟大,伟大是一种本质,Java动态代理就是佐例。

3.CGLIB代理

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。但因为采用的是继承,所以不能对final修饰的类进行代理。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

第一步:创建CGLIB代理类

 1 package dan.proxy.impl;
 2
 3 import net.sf.cglib.proxy.Enhancer;  4 import net.sf.cglib.proxy.MethodInterceptor;  5 import net.sf.cglib.proxy.MethodProxy;  6  7 import java.lang.reflect.Method;  8  9 /** 10  * @Auther: dan gao 11  * @Description: 12  * @Date: 20:38 2018/1/16 0016 13 */ 14 public class CglibProxy implements MethodInterceptor { 15 private Object target; 16 public Object getInstance(final Object target) { 17 this.target = target; 18 Enhancer enhancer = new Enhancer(); 19 enhancer.setSuperclass(this.target.getClass()); 20 enhancer.setCallback(this); 21 return enhancer.create(); 22  } 23 24 public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 25 System.out.println("买房前准备"); 26 Object result = methodProxy.invoke(object, args); 27 System.out.println("买房后装修"); 28 return result; 29  } 30 }

第二步:创建测试类

 1 package dan.proxy.test;
 2
 3 import dan.proxy.BuyHouse;  4 import dan.proxy.impl.BuyHouseImpl;  5 import dan.proxy.impl.CglibProxy;  6  7 /**  8  * @Auther: dan gao  9  * @Description: 10  * @Date: 20:52 2018/1/16 0016 11 */ 12 public class CglibProxyTest { 13 public static void main(String[] args){ 14 BuyHouse buyHouse = new BuyHouseImpl(); 15 CglibProxy cglibProxy = new CglibProxy(); 16 BuyHouseImpl buyHouseCglibProxy = (BuyHouseImpl) cglibProxy.getInstance(buyHouse); 17  buyHouseCglibProxy.buyHosue(); 18  } 19 }

CGLIB代理总结: CGLIB创建的动态代理对象比JDK创建的动态代理对象的性能更高,但是CGLIB创建代理对象时所花费的时间却比JDK多得多。所以对于单例的对象,因为无需频繁创建对象,用CGLIB合适,反之使用JDK方式要更为合适一些。同时由于CGLib由于是采用动态创建子类的方法,对于final修饰的方法无法进行代理。

转载于:https://www.cnblogs.com/xuxinstyle/p/9382219.html

设计模式---代理模式相关推荐

  1. Python设计模式-代理模式

    Python设计模式-代理模式 基于Python3.5.2,代码如下 #coding:utf-8info_struct = dict() info_struct["addr"] = ...

  2. Java设计模式(代理模式-模板方法模式-命令模式)

    Java设计模式Ⅴ 1.代理模式 1.1 代理模式概述 1.2 静态代理 1.2.1 静态代理概述 1.2.2 代码理解 1.3 动态代理之JDK代理 1.3.1 动态代理之JDK代理概述 1.3.2 ...

  3. 设计模式——代理模式

    设计模式--代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能 ...

  4. 23种设计模式----------代理模式(一)

    代理模式也叫委托模式. 代理模式定义:对其他对象提供一种代理从而控制对这个对象的访问.就是,代理类 代理 被代理类,来执行被代理类里的方法. 一般情况下,代理模式化有三个角色. 1,抽象的主题类(或者 ...

  5. java设计模式代理模式_Java中的代理设计模式

    java设计模式代理模式 代理对象或代理对象为另一个对象提供占位符,以控制对该对象的访问. 代理充当原始对象的轻量级版本或简化版本. 它支持与原始对象相同的操作,但可以将那些请求委托给原始对象以实现它 ...

  6. 第四章 Caché 设计模式 代理模式

    文章目录 第四章 Caché 设计模式 代理模式 定义 类型 使用场景 优点 缺点 结构图 完整示例 抽象主题类 真实主题类 代理类 对象类 调用 思考 第四章 Caché 设计模式 代理模式 定义 ...

  7. Android常见设计模式——代理模式(Proxy Pattern)(二)

    文章目录 1. 前言 2. 远程代理(Remote Proxy) 3. 后记 1. 前言 在上篇Android常见设计模式--代理模式(Proxy Pattern)中基本上知道了什么是代理模式,以及对 ...

  8. sheng的学习笔记-设计模式-代理模式

    原理图: 代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. 至少在以下集中情况下可以用 ...

  9. 设计模式-代理模式(Proxy Pattern)

    设计模式-代理模式(Proxy Pattern) 文章目录 设计模式-代理模式(Proxy Pattern) 一.定义 二.概念解释 三.场景 四.实现 1.类图 2.代码实现 五.小结 六.动态代理 ...

  10. 简说设计模式——代理模式

    一.什么是代理模式 关于代理模式,我们听到的见到的最多的可能就是静态代理.动态代理之类的,当然还有大家都知道的Spring Aop,这里我们先不谈这些个代理,先说个简单的例子.游戏代练应该都听说过,许 ...

最新文章

  1. 3745路由器配置简单的dhcp server
  2. 乐观锁与悲观锁各自适用场景是什么?
  3. python手册中文版-python手册中文
  4. Octotree插件安装及API limit exceeded报错
  5. 简单书籍类网页代码制作
  6. 深度解密微信疯读狂加粉的伎俩
  7. 5分绩点转4分_5分绩点转4分
  8. Flutter 2.8 更新详解
  9. 在线支付(易宝支付)
  10. 黄山杭州五日游攻略,厦门出发
  11. 刷宝短视频Auto.js挂机源码讲解
  12. R9 7845HX参数 R97845HX核显怎么样 锐龙R97845HX相当于什么水平
  13. 怎么把html格式转换成数字,怎么把数字转变成文本格式
  14. 互联网应用 zzl复习版
  15. 将数字金额转换为中文大写金额
  16. 集群、分布式、负载均衡区别(转)
  17. 《Computer Graphics C Version》(Donald Hearn著)总结 第五章(第一部分)
  18. 【Excel神技】之 工作表区域保护
  19. Excle中如何快速筛选数据
  20. 《用Chrome学编程》真心话大冒险

热门文章

  1. 使用SAPGUI画图
  2. 使用SAP云平台的destination消费Internet上的OData service
  3. android 缩放透明动画,Android旋转、平移、缩放和透明度渐变的补间动画
  4. java vo转map_Jython:在 Java 程序里运行 Python 代码 4.5
  5. 软件测试理论入门(一)
  6. sklearn 决策树例子_机器学习|决策树的生成过程是怎样?(一)
  7. 北理在线作业c语言,北理线性代数在线作业-20210414115922.doc-原创力文档
  8. 10G_Ethernet_01 万兆以太网设计引言
  9. ad用户和计算机报错,AD常用排错工具
  10. 在共享dll中使用mfc_在SpringBoot中使用Spring Session解决分布式会话共享问题