AOP vs Decorator

本文探讨了AOP(面向切面编程)拦截器与Decorator模式在实现过滤器功能时的差异,分析了它们在软件设计中的适用场景,并讨论了性能和设计复杂性的权衡。

板桥里人 http://www.jdon.com 2006/1/2(转载请保留)

  更确切地说,我们在比较AOP的拦截器和Decorator模式,它们非常相似,一些AOP框架本身就是使用Decorator模式来实现拦截器功能的。

  过滤器是架构设计模式中比较常用的一种,几乎每个灵活动态系统都需要过滤器,特别是当我们的数据以内存状态出现时,过滤器无疑成为领域层的一个核心业务逻辑,当然如果你还是使用面向数据库的编程模式,过滤器功能就被你用SQL语句的where语法给替代了,那么以下你可能不必再看,请浏览这篇文章:状态对象:数据库的替代者

  当我们在一个AOP框架下编程,经常会问自己,到底过滤器这个功能是应该做成拦截器还是
Decorator,当我在Jdon Framework下重写JiveJdon时就不只一次的问我自己。

  其实这是一个分析模式中的过滤器实现问题,也是一个现实设计的问题:在Servlet Filter和职责链以及装饰模式Decorator和AOP几个方面如何选择?

  选择标准无外乎软件的两个终极目标:简单和高质量;高质量是反映在细粒度方面,简单则是在进行设计实现时比较容易方便。

  在粒度粗细方面,又有一个衡量指标:功能覆盖范围,也是一个scope,例如:如果功能需求要为某个类的方法实现实现过滤,但是,你使用一个Servlet Filter这样过滤器实现,虽然
它也能够实现我们的目标,但是它对所有的Servlet请求都进行过滤,这无疑范了杀鸡取卵的错误,造成系统性能上的损失。

  以一个具体案例为例子:
  我们在论坛显示时,希望动态过滤掉不应该出现的字眼,也就是在帖子显示之前,加载一个过滤器,对内容进行替换。

  这里的Model是ForumMessage,而对应的Service则是ForumMessageService; ForumMessageService的getMessage可以获得帖子内容,这里我们在getMessage之前加一个过滤器;那么这里应该如何选择呢?

  因为我在Jdon Framework这样的Ioc/AOP框架下实现,所以想到的是AOP,我们定义一个拦截器,拦截的对象是ForumMessageService的getMessage方法,进行配置文件配置即可。似乎很简单很酷,可是真的很美丽吗?

  这里,我们从原理上这几个过滤器实现进行解析一下:
  我这里举个例子,你想向处于同一个城市对方送达一个信件,这时有两种选择:
  1.委托高效的TNT UPS等快递公司
  2.亲自跑一趟。

  这两种哪个效率最高?无疑是亲自跑一趟,可能半个小时或一个小时解决问题,但是你一旦委托第三方,我想,无论快递公司如何高效,肯定没有你自己解决快速。所以,当你能够自己处理把握时,亲自动手无疑最快的。

  编码时也类似这样,如果你能在编码时,能够确定拦截那个类哪个方法,有什么比你直接写代码还能执行更快的呢?

  AOP的拦截器实现原理也是这样,当然,正是有这种考虑,所以所有AOP框架内,只有 AspectJ性能是最好的,因为它在你编译代码时就将你的拦截意图实现了,这属于静态织入 weaving,这就类似你自己写代码实现,但是与你自己写代码不同的是,你自己不但要写拦截器,而且还要自己手工将拦截器语句插入被拦截的那段代码,现在,使用AspectJ你就不用做后者了,这也是整合了AspectJ的Spring 2.0给我们带来的效能。所以,为了在编译代码时做手脚,就不能使用SUN的JDK原来的javac了,必须用他们自己特定的javac了。有得必有失吧。

  理解了AOP拦截器拦截的原理,你可能感慨:原来所有的动态AOP(不改换编译器的AOP框架)拦截效能没有Decorator直接指定要快啊。所以,如果你在编码设计阶段,可以知道你所要拦截的方法,那么,无疑直接使用Decorator模式组成过滤器是一种好方式。

  这也是我先期不怎么看好使用动态AOP实现的Spring 1.X版本,也不太热衷于同样使用
动态AOP实现、虽符合EJB 3.0规范的JBoss 4.0了。可是,为什么总是有人迫不及待地告别EJB 2.x,夸张Spring,然后又狂炫EJB 3.0。在接纳他们之前,先把盒子打开看看验货一下,做一个普通的消费者应有的理性。

  当然,不是说动态AOP没有用武之地,它类似SOA的集成作用,可以在不用修改原来代码结构上强行加入过滤器。而且AOP不只是拦截器,还有introduction,这一神奇功能可以突破Java单继承法则,显得象儿童世界里面的神奇魔法一样。

  从某个方面来说,动态AOP和职责链非常类似,职责链类似击鼓传花,更像典型的打太极拳,推来推去,这也是政府效率不高的主要原因,同样,用在软件系统里,性能最差。想象一下,当这朵花传到真正主人面前时,而这个主人是传花环节中最后一个,这种效率和直接抛绣球一样,直接将花抛给真正主人相比,无疑最耗时间的,所以击鼓传花游戏就是玩的这个耗时间,在鼓声中,消耗时间,煎熬折磨你的心思,它玩的不是要把花如何快速准确地送给某人,它的目的性不确切。

  我们的软件系统不能这么玩吧?

  总结如下:过滤器实现方式在不保证功能前提下,从性能角度考虑有如下先后顺序:Decorator或Proxy模式;AOP拦截器。

  考虑使用AOP拦截器时,最好选择那些受众面积比较广的功能,例如一些基础通用功能:权限检查;事务机制;Pool等,这些功能不是针对某个具体类或方法(方法权限除外),而是一系列类,这样使用动态AOP拦截器,就是有些性能损耗也是值得的,而且是必要的,使用其他方法也会引起这样的损耗。

  如果过滤器是业务逻辑的一部分,而且在设计时,我们可以确定这些过滤器,这样我们使用Decorator模式或Proxy模式进行特定指定的拦截,当然,因为每个类/接口都需要一个附加的Decorator/Proxy,如果某个过滤功能是很多类都需要的,会形成很多Decorator/Proxy附加类,当点形成面时,这时AOP切面概念就应该浮现在你脑海,这时升级使用AOP拦截器就更好。Decorator/Proxy在点上针对性相当强,特别在这个点上有一系列过滤器需要实现时。

  职责链和Decorator/AOP拦截器是有些区别的,在一个动态运行系统中,有两个概念:由客户端触发的请求对象,该请求对象需要穿透一系列过滤器(防火墙),最终可能达到持久层数据库。Decorator/AOP拦截器是对过滤器管理的一种模式,也就是说:怎么设计过滤器类;过滤器类关系是怎样;而职责链不是对类关系管理定义,而是为了处理某个请求对象而实现的。他们区别在于目标对象不一样,所以职责链是一种很具体的行为。

  在这个层面上,Command模式和其是相竞争的,Command模式类似直接抛绣球,知道目的,能够最有效率,但是前提在设计编码阶段你必须知道你的目的地;Command模式和职责链的区别与Decorator和AOP拦截器的区别是类似的。

 
<think>好的,我现在需要帮用户理解AOP(面向切面编程)的概念、用法和实现。首先,我得回忆一下自己之前学过的关于AOP的知识,同时结合用户提供的引用资料,确保信息准确。 用户提供的引用中有几个关键点:AOP将程序逻辑分解为不同的关注点(concerns),支持在源代码层面模块化这些关注点,提到AspectJ和Eclipse环境的应用,还有AOP在软件质量和维护中的作用。我需要整合这些信息,用清晰的结构呈现出来。 首先,AOP的核心概念是横切关注点。传统OOP中,像日志、安全这样的功能会分散在各个模块,导致代码重复和耦合。AOP通过切面将这些横切关注点模块化,比如引用[1]和[3]都提到模块化concerns。接下来,需要解释AOP的术语,比如切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等,这些是理解AOP的基础。 然后,用法方面,用户可能想知道如何实际应用AOP解决问题。比如在日志记录、事务管理、权限检查等场景,通过AOP可以将这些逻辑集中管理,提高代码的可维护性。引用[2]和[4]提到使用AspectJ和Eclipse工具,所以应该举例说如何在Java中使用AspectJ实现,比如定义切面和通知。 实现部分需要介绍具体的工具和框架,如AspectJ、Spring AOP,比较它们的区别。比如AspectJ提供了更强大的功能,而Spring AOP更易于集成。同时,代码示例是必要的,用户提供的示例中有Python代码,但引用中主要讨论Java和AspectJ,所以可能需要调整,给出AspectJ的示例代码,比如定义一个切面和前置通知。 用户可能存在的疑问包括AOP与OOP的区别,适用场景,以及实际项目中的最佳实践。因此,相关问题部分可以引导他们进一步探索性能影响、设计模式结合、与其他编程范式对比等。 需要确保回答符合用户的要求:结构清晰,分步骤解释,引用资料正确标注。同时检查LaTeX格式是否正确,数学公式用$...$,独立公式用$$...$$,但这里可能不太涉及数学公式,所以主要注意代码块和引用标注。 最后,生成的相关问题需要围绕AOP的深入应用、实现细节和比较展开,帮助用户继续学习。例如,如何选择AOP框架,AOP在微服务中的应用,或者AOP可能带来的挑战。 现在整理这些思路,组织成一个连贯的回答,确保每个部分都涵盖概念、用法、实现,并引用提供的资料作为支持。</think>### AOP(面向切面编程)的概念、用法与实现 #### 1. **核心概念** AOP(Aspect-Oriented Programming)是一种编程范式,旨在通过**模块化横切关注点(cross-cutting concerns)**来提升代码的复用性和可维护性[^1][^3]。横切关注点指那些跨越多个模块的功能(如日志、权限、事务管理),在传统面向对象编程(OOP)中,这些功能会分散在代码各处,导致冗余和耦合。 - **切面(Aspect)**:封装横切关注点的模块,例如日志切面、事务切面。 - **连接点(Join Point)**:程序执行中的特定点(如方法调用、异常抛出)。 - **通知(Advice)**:在连接点执行的动作(如前置通知、后置通知)。 - **切点(Pointcut)**:定义哪些连接点会触发通知的表达式。 - **引入(Introduction)**:为类动态添加方法或属性。 #### 2. **典型用法** AOP 主要用于以下场景: - **日志记录**:统一记录方法调用参数、耗时等。 - **事务管理**:自动开启或回滚数据库事务。 - **权限校验**:拦截未授权访问请求。 - **性能监控**:统计方法执行时间。 例如,使用 AspectJ 实现日志记录: ```java @Aspect public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void logMethodCall(JoinPoint joinPoint) { System.out.println("调用方法: " + joinPoint.getSignature()); } } ``` 此代码会在 `com.example.service` 包下所有方法执行前输出日志[^4]。 #### 3. **实现方式** AOP 可通过以下工具实现: - **AspectJ**:功能最完整的 AOP 框架,支持编译时织入(CTW)和加载时织入(LTW)[^2]。 - **Spring AOP**:基于动态代理实现,仅支持方法级别的连接点,依赖 Spring 容器。 - **其他语言支持**:如 Python 的 `decorator` 和 C# 的 `PostSharp`。 #### 4. **优势与挑战** - **优势**: - 减少代码重复,提升可维护性。 - 将核心业务逻辑与辅助功能解耦[^1]。 - **挑战**: - 过度使用可能增加调试难度。 - 需权衡运行时性能(如动态代理的开销)。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值