详解Proxy代理模式的场景分析

代理模式是一个十分优秀的软件架构模式,许多应用都用到了代理模式。代理模式就是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不合适或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

这次主要讲解一下代理模式的实例、解决的问题部分。

在java框架中有一种框架就用到了动态代理模式,spring框架中的aop技术,基于代理模式。下面我将以beforeAdvice来进行这个模式的介绍。

image

这张图反映了参与到AOP过程中的几个关键组件(以@Before Advice为例):

  1. 调用者Beans - 即调用发起者,它只知道目标方法所在Bean,并不清楚代理以及Advice的存在
  2. 目标方法所在Bean - 被调用的目标方法
  3. 生成的代理 - 由Spring AOP为目标方法所在Bean生成的一个代理对象
  4. Advice - 切面的执行逻辑

它们之间的调用先后次序反映在上图的序号中:

  1. 调用者Bean尝试调用目标方法,但是被生成的代理截了胡
  2. 代理根据Advice的种类(本例中是@Before Advice),对Advice首先进行调用
  3. 代理调用目标方法
  4. 返回调用结果给调用者Bean(由代理返回,没有体现在图中)

在使用Spring AOP的时候可能会遇到的一个问题。类似这种间接调用不会触发Advice的原因在于调用发生在目标方法所在Bean的内部,和外面的代理对象可是没有半毛钱的关系哦。我们可以把这个代理想象成一个中介,只有它知道Advice的存在,调用者Bean和目标方法所在Bean知道彼此的存在,但是对于代理或者是Advice却是一无所知的。因此,没有通过代理的调用是绝无可能触发Advice的逻辑的。

代理模式的应用场景还有延迟加载场景,延迟加载的思想:如果当前没有使用这个组件时,则不需要真正地去初始化它,而是用一个代理对象去替代它的原有位置。当真正需要使用的时候,才对它进行加载。使用代理模式实现延迟加载是很有意义的,首先从时间轴上分散系统的压力,尤其在系统启动时,不必完成所有的初始化工作,从而加速启动时间;其次,对于很多真事主题而言,在软件启动到系统关闭的整个过程,可能都不会被调用,初始化这些数据无疑是一种资源的浪费。

假设某客户端软件,根据用户请求,去数据库查询数据的功能。在数据库查询前需要获得数据库连接。在系统启动时,初始化系统所有的类,此时尝试获得数据库连接。当系统存在大量类似的操作时(XML解析等),所有这些初始化操作都必须叠加,使得系统很慢。为此,使用代理模式,使用代理类,封装对数据库的查询操作。当系统启动时,初始化这个代理类,而非真实的数据库查询类,而代理类什么都不做。当真正开始查询的时候,才初始化查询对象。

代理模式的应用场景主要还是分为4类:

远程代理:为一个对象在不同地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实,例如:老阮(MrRuan)在地点A,老李在地点B,餐厅柜台也在地点B,那么老李和老软住在一起(都在地点A住),那么老李就是餐厅(地点B)在老软与老李住处(地点A)的代表。

   虚拟代理:是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真是对象,例如:老阮(MrRuan)在地点A,到餐厅柜台(地点B),因为距离远却是很费劲,而老李刚好在这里(地点B)上班,所以让老李去办是很可行的办法。(不太恰当)

   安全代理:用来控制真是对象访问时的权限,例如:老阮跟餐厅的柜台MM刚分手不方便去办理,所以需要借助老李去完成事项的办理。

   智能代理:是指当调用真是的对象时,代理去处理另外一些事情,例如:老李帮助老阮办理卡片激活时,顺便说说老阮的好话,让她俩能够和好。

WebService也是应用到了代理模式,我们来看一下WebService的示例过程:

image

实现一个完整的Web服务包括以下步骤:

◆ Web服务提供者设计实现Web服务,并将调试正确后的Web服务通过Web服务中介者发布,并在UDDI注册中心注册; (发布)

◆ Web服务请求者向Web服务中介者请求特定的服务,中介者根据请求查询UDDI注册中心,为请求者寻找满足请求的服务; (发现)

◆ Web服务中介者向Web服务请求者返回满足条件的Web服务描述信息,该描述信息用WSDL写成,各种支持Web服务的机器都能阅读;(发现)

◆ 利用从Web服务中介者返回的描述信息生成相应的SOAP消息,发送给Web服务提供者,以实现Web服务的调用;(绑定)

◆ Web服务提供者按SOAP消息执行相应的Web服务,并将服务结果返回给Web服务请求者。(绑定)

总之,许多都应用到了代理模式,在使用的时候认真查看原理,对代理模式加深自己的理解。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

大型服务端开发的反模式技巧

1. 用线程池执行异步任务 ? 为了减少阻塞时间,加快响应速度,把无需返回结果的操作变成异步任务,用线程池来执行,这是提高性能的一种手段。 你可能要惊讶了,这么...

3345
来自专栏cloudskyme

跟我一起数据挖掘(17)——分布式缓存

分布式缓存架构 先看架构: ?                                                     图一 用户通过访问htt...

3407
来自专栏解Bug之路

解Bug之路-记一次对端机器宕机后的tcp行为

机器一般过质保之后,就会因为各种各样的问题而宕机。而这一次的宕机,让笔者观察到了平常观察不到的tcp在对端宕机情况下的行为。经过详细跟踪分析原因之后,发现可以通...

903
来自专栏用户画像

2.5.2 死锁与饥饿

 具有等待队列的信号量的实现可能导致这样的情况: 两个或多个进程无限地等待一个事件,而该事件只能由这些等待进程之一来产生。这里的事件是V操作的执行(即释放资源)...

622
来自专栏C#

NodeJS异步I/O解析

    在现在的项目开发中,任何一个大型项目绝对不是简简单单的采用一个种语言和一种框架,因为每种语言和框架各有优势,与其死守一个,不与取各家之所长,依次得到一个...

2039
来自专栏TSW

5201314对程序员意味着什么?

作为年轻人的潮流聚集地,Qzone在每个特殊的日子总会迎来一波猛烈的流量冲击。比如刚过去的520,下图是今年5月20号的流量情况:

2067
来自专栏后端技术探索

基于Redis实现分布式消息队列(一)

1、为什么需要消息队列? 当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消息队列,作为抽象层,弥合双方的差异。

1093
来自专栏铭毅天下

Elasticsearch究竟要设置多少分片数?

0、引言 本文翻译自Elasticsearch20170918热乎的官方博客,原作者:Christian Dahlqvist。 在构建Elasticsearch...

65410
来自专栏程序你好

一个微服务架构的简单示例

1243
来自专栏程序你好

Apache Spark大数据处理 - 性能分析(实例)

今天的任务是将伦敦自行车租赁数据分为两组,周末和工作日。将数据分组到更小的子集进行进一步处理是一种常见的业务需求,我们将看到Spark如何帮助我们完成这项任务。

1083

扫码关注云+社区