jinfeng_wang

G-G-S,D-D-U!

BlogJava 首页 新随笔 联系 聚合 管理
  400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks
原文地址:http://www-900.ibm.com/developerworks/cn/java/j-aopwork1/index.shtml
英文地址:http://www-128.ibm.com/developerworks/java/library/j-aopwork3/


AOP@Work:
AOP 工具比较,第 1 部分

内容:
选择成熟的工具
都是为了连接点
方面比较
语法差异
语义的相似性
语言机制
结束语
参考资料
关于作者
对本文的评价
相关内容:
AOP Tool comparison, Part 2: Development environments
A look at aspect-oriented programming
Aspect-oriented development with Eclipse and AJDT
订阅:
developerWorks 时事通讯
developerWorks 订阅
(订阅CD 和下载)
语言机制

级别: 中级

Mik Kersten
AOP 工具构建师、咨询顾问, University of British Columbia
2005 年 2 月

AOP 技术的时代已经来临,但是怎样才能为项目选择正确的工具呢?在新推出的 AOP@Work 系列的第一篇文章中,面向方面(aspect-oriented)的编程专家 Mik Kersten 将比较 4 个领先的 AOP 工具(AspectJ、AspectWerkz、JBoss AOP 和 Spring AOP),帮助大家判断应该选择哪一个工具。本文由两个部分组成,在文中,作者将重点介绍这些工具的语言机制和不同技术的优劣。他分别用 4 种工具编写同一个示例,让读者感觉到它们之间的高级区别。他还将讨论每种工具的语法技术对 AOP 语义产生的效果。在文章结束时,作者将对工具的核心语言机制(例如切入点匹配和组合、通知的格式、连接点上下文)进行深入比较。注意,本文将解释最近宣布的 AspectJ 和 AspectWerkz 项目合并的意义。

面向方面编程(AOP)在 Java™ 平台上变得日益流行。随着 AOP 出版物和会议的增加,这项技术的工具与实现越来越多。虽然人们很清楚 AOP 是面向对象技术的补充,但是 Java 开发人员该如何评估当前的 AOP 工具,特别是每项新技术实现的优劣,这方面则相对不那么清楚。

本文有两部分,而且本文还是 developerWorks 上一个新的 AOP 系列的第一篇文章。在本文中,将概述 AOP 工具当前的技术状况,比较对于该技术而言最成熟的一些方法:AspectJ、AspectWerkz、JBoss AOP、和 Spring AOP,并对比与每种方法的采用有关的问题。文中还会解释最近宣布的 AspectJ 和 AspectWerkz 项目合并的意义(请参阅参考资料)。

本文无意作为 AOP 的介绍或某个特定 AOP 实现的入门读物。而是将对目前使用最普遍的 AOP 技术进行概述。对每个工具的语言机制和工具支持的内在优劣进行探讨,将有助于为项目选择最合适的技术。这里定义的指标还会让读者更加容易地评估即将推出的 AOP 工具和特性。关于 developerWorks 上介绍 AOP 的最新文章列表,请参阅参考资料

请注意本文有两个部分,为了方便读者,两部分同时发布。第 1 部分侧重于这 4 个领先工具各自的 AOP 语言机制处理技术,其中包括工具的方面语法(aspect syntax)和切入点的表示、用来声明方面的机制范围等主题。第 2 部分继续深入介绍领先的 AOP 实现如何与现有的开发环境、工具和库进行集成。这一部分包括以下主题:方面设计器、IDE 插件、可伸缩性和 AOP 工具将来的发展方向,还包括对最近 AspectJ 和 AspectWerkz 项目合并的关注。

选择成熟的工具
AOP 是一项新技术,所以,并不是现有的所有工具都已经成熟到适用于商业开发。判断成熟度的一个主要因素是用户的采用程度。在考虑把一项新编程技术应用到商用之前,这项技术必须从活跃的用户社区的反馈中得到强化。表 1 显示了 aosd.net 上列出的目前可以使用的 AOP 工具(请参阅参考资料)。每个工具的用户列表贴子数量可以表明它的用户基数(省略了贴子的实际数量,因为单独一个月的统计可能给读者造成误解)。

表 1. 在 2004 年 11 月 AOP 工具用户列表中的贴子数量

关于这个系列
AOP@Work 系列面对的是在面向方面编程上有些基础,同时想扩展或加深这方面了解的开发人员。同 developerWorks 的大多数文章一样,这个系列非常实用:读完每篇介绍新技术的文章,都可以立即将其投入使用。

为这个系列选择的每个作者都是面向方面编程领域的领导或专家。许多作者都是系列文章中介绍的项目和工具的参与者。每篇文章都力图提供一个中立的评述,以确保这里表达的观点的公正与正确。

请就文章的评论或问题分别与这些文章的作者联系。要对这个系列整体进行评论,可以与这个系列的负责人 Nicholas Lesiecki 联系。

关于本文
本文并不想突出某一个工具,而是要用一种批判的、没有偏见的方式突出每个工具的优势与不足。虽然作者是 AspectJ 项目的参与者之一,但是在编写本文的时候,也咨询了其他 AOP 工具项目的领导人,以确保公平地展示所讨论的技术。

请注意 Spring 的 AOP 部分没有形成一个独立的下载或用户社团,所以用户基数相当比例的用户可能没有给 Spring AOP 发贴,而是投在别的主题上了。在 aosd.net 上还列出了 4 个额外的工具,但是它们要么缺乏用户讨论论坛,要么在 11 月没有贴子。

AOP 工具虽然没有列在表中前四位,但它在技术上可能非常成熟,可是缺乏较大的用户基数就意味着它们还没有经受过采纳程度测试。虽然在本文编写的时候,它们还不适合于商业开发,但是这些工具的日后发展还是值得关注的。通过上表的比较,还可以看出非 Java 平台的 AOP 工具没有 Java 平台的工具成熟,但是应当注意 .NET 和 C++ 工具的用户社区正在成长。

根据表 1,可以看出,从用户采用度的角度来说,AspectJ、AspectWerkz、JBoss AOP 和 Spring AOP 是领先的工具。所有这些工具都是适合用于商业开发中的开源项目。按字母顺序将它们排列如下,包括它们 V1.0 版本的发布日期:

  • AspectJ —— 2001 年由 Xerox PARC 的 AOP 小组发行。目前主页在 eclipse.org 上,由 IBM 支持。版本已经更新到 1.2.1。

  • AspectWerkz —— 2002 年发布,由 BEA Systems 支持。版本更新到 2.0RC2。

  • JBoss AOP —— 2004 年作为 JBoss 应用程序服务器框架的扩展发布。版本更新到 1.0。

  • Spring AOP —— 2004 年作为 Spring 框架的扩展发布。版本更新到 1.1.3.

都是为了连接点
本文介绍的每个 AOP 工具都采用了连接点(join point)模型和机制,显式地声明程序的横切结构。虽然各个工具实现这个框架的技术非常相似,但是理解底层机制对于了解每项技术的优劣是非常重要的。在这一节中,将回顾 AOP 的连接点模型以及利用连接点模型的语言模型。

支持机制
AOP 工具的设计目标是把横切的问题(例如认证和事务管理)模块化。在单独使用面向对象技术实现的的时候,处理这些问题的代码会分散在整个系统中,这种分散造成管理和发展横切结构时出现不必要的困难。与对象提供了一种能够清楚地捕获继承结构的语言机制类似,AOP 也为横切问题的良好模块化提供了同样的好处。位于每个 AOP 工具核心的是连接点模型,它提供了一种机制,可以识别出在哪里发生了横切。

连接点 就是主程序和方面相遇的地方。静态连接点允许方面定义类上的新成员。动态连接点是方面执行与程序执行相遇的地方。例如,普通的 Java 程序执行方法调用、字段设置这样的连接点。再比如说,请考虑一下这样一个问题:对改变 Account 状态的活动进行监视,就像在 Ramnivas Laddad 的 AspectJ in Action 一书中讨论的那样(请参阅参考资料)。 图 1 中的顺序图突出了在 Account 操作上形成的一些动态连接点。

图 1. 突出了选中的动态连接点的 UML 序列图

下面的编号与图中的编号对应:

  1. 方法执行 连接点,与方法返回之前的生命周期对应。

  2. 控制流程 捕捉在控制流程序列中出现的各个连接点;在这个例子中,在 debit() 方法调用下方的序列描述了在 debit() 调用中发生的全部连接点。

  3. 字段访问 连接点对应着字段的读和写;在这个例子中,在 Account 类上对 name 字段进行了赋值。

AspectJ 和 AspectWerkz 项目合并
AOP 技术正在迅速地向前发展,在本文的第 2 部分突出了领先的 AOP 工具的预计的发布计划。有一个那些思想超前的读者会特别感兴趣的主题,这就是最近 AspectJ 与 AspectWerkz 项目的合并,这一合并会给 AOP 的发展前景带来重大的变化。一些开发人员在这些项目上进行合作,生产 AspectJ 5,这是一种单一工具,融合了这里介绍的 AspectJ 和 AspectWerkz 的语法。

重要的是要注意 AspectWerkz 并没有正在消失。它将成为编写 AspectJ 程序的另一种方法,并更名为 @AspectJ 风格。在这里可以看到,语法是 AOP 实现之间的主要区别因素,而核心的 AOP 机制通常非常相似。 AspectWerkz 和 AspectJ 的相似性使得这两种技术可以联合。合并可以在提供方面语法的时候提供更多的灵活性,同时保留着关键的好处(例如静态类型化和成熟的工具支持)。有关合并的细节以及相关文档,可以从参考资料中得到。虽然本文重点放在立刻就可以开始使用的工具上,但是这里概述的指标和优劣也适用于未来的发行版(例如 AspectJ 5)。

切入点、通知和类型间声明
AOP 工具提供了识别连接点集合的机制,叫作切入点(pointcut)通知(advice) 机制指定在程序执行过程中遇到匹配的切入点时应当采取什么行动。另外,类型间声明(inter-type declaration)(开放类或混合类提供了在现有类型上声明额外成员的方法。切入点、通知和类型间声明组合在一起,使 AOP 语言可以清楚地表达横切问题。方面 声明可以在标准的 Java 字段和方法之外包含这三类成员。方面代表一套模块化良好的横切结构。如下所示,不同的 AOP 技术实现这些方法的技术各不相同。但是,每种技术的核心,都是连接点的访问、编辑、命名和抽象机制。

切入点可以通过显式枚举方式描述连接点集合。应当用一个示例指定图 1 所示的 Account 的利息的三个方法调用。虽然枚举可能很有用,但是用结构化属性的方式表示连接点通常更方便。这类基于属性的切入点可以表示一套与“每个针对 Account 子类型的调用”匹配的连接点,却不必强迫程序员枚举这些子类型。这样做可以保证向系统添加由 Account 扩展的新类时,新类会自动与切入点匹配。

切入点支持复合(composition),这就允许把简单的切入点组合成更复杂的切入点。例如,可以把所有 Account 调用的切入点限制在那些针对特定类或控制流程进行的调用中。切入点的命名(naming)机制提高了可读性和复合性。对抽象(abstraction)具体化(concretization)的支持,可以更加容易地创建通用库,对于要应用库的特定应用程序的切入点来说,这些库可以独立定义。最后,对切入点中公开连接点状态 的支持允许对诸如正在执行对象和方法参数之类的访问事项进行商量。

方面比较
如前所述,所有 AOP 工具的底层机制都是连接点和切入点、通知和类型间声明的概念。在这些工具中,可以注意到的主要区别就是方面声明编写及应用到系统上的方式。这些工具可用以下方法中的一种进行方面声明:使用类似 Java 的代码、注释或 XML。对于某些开发人员来说,熟悉用 Java 语言编程方面的知识,要比熟悉语言扩展技术的优劣更重要,这些内容会在后面的小节中讨论。对于其他人来说,了解注释和 XML 技术在集成上的优势,要比痛苦地把切入点当作字符串来操作更重要。

在这一节中,将使用一个常见的示例指出每个工具在方面声明技术上的差异。请考虑图 1 所示的 Account 类的授权策略这样一个示例。在面向对象的实现中,最常见到的,就是对认证的调用分散在 Account 类的众多方法以及需要认证的其他类中。在 AOP 实现中,可以明确地用一个方面捕获这个行为,而不必修改操纵帐户的代码。不管使用什么工具声明,这个方面都需要具备以下特征:

  • 一个切入点,捕捉 banking.Account 类上所有公共方法的执行。
  • 一种引用正在认证的 Account 的方式。

  • 通知,在切入点指定的连接点上调用 Account 的认证。

现在,请看这几个领先的 AOP 工具各自是如何处理这个方面的。

AspectJ
Aspect 中的方面声明类似于 Java 语言中的类声明,如图 2 所示。由于 AspectJ 是 Java 语言语法和语义的扩展,所以它提供了自己的一套处理方面的关键字。除了包含字段和方法之外,AspectJ 的方面声明还包含切入点和通知成员。示例中的切入点使用了修饰符(modifier)和通配符(wildcard)模式来表达“所有公共方法”。对帐户的访问,由 pointcut 参数提供。通知使用这个参数,而切入点则用 this(account) 把它绑定。这样做的效果,就是捕获了正在执行的方法所隶属 Account 对象。否则,通知的主体与方法的主体相似。通知可以包含认证代码,或者就像在这个示例中一样,可以调用其他方法。

图 2. AspectJ 的方面

构建 AspectJ 程序与构建 Java 程序类似,其中包括调用 AspectJ 的递增编译器,构建所有的项目源文件,包括普通的 Java 源文件。运行 AspectJ 程序也与运行 Java 程序一样,请注意要把 aspectjrt.jar 库添加到类路径中。要对在系统中应用哪个方面进行配置,必须把它们加入包含列表或从中删除,包含列表会传递给编译器,可以通过 IDE 支持传递包含列表,如果正在 Ant 环境或命令行进行工作,也可以通过“.lst” 包含文件传递。注意,在第 2 部分中,将讨论构建 AOP 程序的细节以及方面设计的概念。

AspectWerkz
AspectWerkz 和 AspectJ 之间的重要区别就是: Authentication 现在是一个普通的 Java 类,而不是一个方面。AspectWerkz、JBoss AOP 和 Spring AOP 都在没有改变 Java 语言语法的情况下加入了方面语义。AspectWerkz 提供了两种进行 AOP 声明的途径。最常用的是注释,注释可以采用图 3 中的 Java V5.0 风格,也可以为了与 J2SE V1.4 兼容采用 Javadoc 风格。AspectWerkz 还支持另外一种基于 XML 的方面声明风格。XML 风格与下面介绍的 JBoss AOP 的风格类似,把方面声明放在单独的 XML 文件中。

请注意通知就是普通的方法声明。按照约定,它被当作不同类型的方法声明,因为不应当显式地调用它,而是应该在满足特定切入点时自动运行它。AspectWerkz 的切入点声明是附加到切入点“方法”的字符串值,也可以在 XML 文件中独立存在。所以,没有切入点的 import 机制,所有的类型引用必须完全规范。对正在运行的 Account 对象的访问技术与 AspectJ 相同。请注意,规划的 @AspectJ 语法看起来与 AspectWerkz 注释的语法非常相似。

图 3. AspectWerkz 的方面

构建 AspectWerkz 程序会涉及一个标准的 Java 构建,然后会涉及到后处理。要运行 AspectWerkz 程序,必须把 AspectWerkz 库放在类路径中。在使用不可插入的方面的情况下,由 aop.xml 文件配置系统中一些方面的包含情况。

JBoss AOP
JBoss AOP 基于 XML 的方面来声明风格,如图 4 所示。JBoss 也支持与图 3 所示相似的注释风格。在 XML 风格中,方面、切入点和通知声明都以 XML 形式表示的。通知的实现,用的是普通的 Java 方法,由 JBoss AOP 框架调用。切入点和切入点到通知的绑定都在方面中用 XML 注释声明。JBoss 没有显式地绑定 Account 参数,而是提供了对当前正在执行的对象的反射访问,因此需要把类型转换到对应的类型。注意,即将发布的 JBoss 会提供一些静态类型的切入点参数来解决这一问题。

图 4. JBoss AOP 的方面

用 JBoss 构建方面只包括普通的 Java 构建。JBoss AOP 的运行时截取框架(interception framework)负责管理切入点匹配和通知调用。需要对启动和类路径做一些配置,但是 JBoss AOP 的 IDE 插件替用户做了这些工作。方面在 jboss-aop.xml 文件中配置。

Spring AOP
查看图 5 中的 Spring AOP 示例时,可以注意到其中的 XML 比前面介绍的技术多。与 JBoss AOP 类似,Spring 的通知实现是带有特殊参数的 Java 方法,由 Spring 框架调用。XML 描述 accountBean,Spring 框架通过它访问 Account 对象,包括通知使用的拦截器 advisor 及其匹配模式,还有应用到模式的向前(before) 通知。

图 5. Spring AOP 的方面

Spring AOP 的技术虽然提供了更加精细的配置,但在将它用于 XML 时,它与 JBoss AOP 非常类似。构建、运行和配置 Spring AOP 方面的过程与 JBoss AOP 相同,但 Spring AOP 依赖的是 Spring 框架方便的、最小化的运行时配置,所以不需要独立的启动器。请注意,使用这个技术,只能通知从 Spring 框架检索出的对象。

语法差异
正如上面的图所展示的,AOP 工具之间的关键差异就是处理方面声明的方式。AspectJ 是 Java 语言的扩展,用它可以完全在代码中对方面进行声明。AspectWerkz 和 JBoss AOP 支持用方面元数据对 Java 代码进行注释,或者在独立的 XML 文件中对方面进行声明。在 Spring AOP 中,则完全用 XML 对方面进行声明。所以,在三种不同的技术中,对方面进行编程的感觉可能非常不同。用 AspectJ 的代码风格,方面和切入点声明感觉起来就像 Java 代码。而用 JBoss AOP 或 AspectWerkz 的注释风格,感觉起来就像在现有 Java 元素上做的附加标签。而用 Spring AOP 风格,以及 AspectWerkz 和 JBoss AOP 的 XML 风格 时,感觉就像使用独立的声明性 XML 语言。

每种技术都有它的优势,具体要由使用者决定哪个更适合需求。所以在这一节,将简要地讨论一些能够有助于进行决策的要点。

自己的风格是什么?
不管选择哪个 AOP 工具,使用通知主体时只涉及到使用 Java 代码。如果需要修改切入点,那么区别是非常透明的。在使用 XML 风格时(就像在 Spring AOP 中),修改切入点包括:从通知找到 XML 文件中对应的切入点声明。从正面来说,这项技术把切入点和方面配置的工作全都局限于本地,但是如果要编辑许多通知和切入点,而且要在 Java 和 XML 之间重复地翻来覆去,那么这项工作就会变得很繁琐。

如果使用 AspectWerkz 或 JBoss AOP 提供的注释风格,那么就可以把切入点的表达值从 XML 转移到 Java 成员的注释。这样可以更容易地并发处理通知体和切入点。如果选择了 AspectJ 的代码风格,那么就会发现处理切入点感觉就像处理代码,而不像是处理非结构化的字符串值。从 Java 代码能得到的一切(例如“import”语句),都可以用于切入点。对比之下,如果用 AspectWerkz、JBoss AOP 和 Spring AOP 的 XML 和注释风格,总是需要在规范切入点中的类型引用。

简洁还是繁琐?
方面声明的风格对每个工具中使用的方面有很大的影响。例如,支持在 XML 中声明方面的工具,也支持在同一 XML 文件中对方面应用到系统的方式进行配置。在前面的小节中,只展示了切入点和方面声明,但是类型间声明同样受到风格选择的影响。在 AspectJ 中,类型间方法声明看起来就像正常的方法声明,引用的技术也一样。而在其他技术中,则要指定一个类,扩展额外的混合类并继承那些额外的成员,通过注释或 XML 添加新方法。注意,目前 AspectJ 是惟一提供使用切入点的静态强制机制的工具。表 2 比较了这些工具对 AOP 语法的关键元素的处理技术。

表 2. 比较领先的 AOP 工具中的语法

显然,从图 2-5 的方面声明来看,代码风格是处理 AOP 声明最简洁的技术。它不需要对通知命名,也不需要显式地调用通知。代码风格不需要显式地把通知绑定到切入点(就像 XML 风格那样),也不需要把通知绑定到 return 语句(这是 AspectWerkz 的切入点“方法”所需要的)。对于可以在 图 3图 4 的 XML 中看到的复杂设计,AspectJ 对 Java 语言进行的语法扩展允许直接表示这些设计。用 AspectJ 编写方面,感觉起来更像是编写 Java 代码,避免了冗余的键入,因此出错也就更少。从不好的一面来说,Java 的语法扩展代价巨大,而注释和 XML 风格有它们独特的优势。最明显的就是 XML 风格可以控制切入点和通知的绑定。这对于扩展和配置方面非常有益,在下面一节中将讨论这点以及不同风格带来的其他优缺点。

代码风格与注释和 XML 的比较

那么,应当采用代码风格,还是用注释或 XML 声明方面呢?以下是基于 AspectJ 的 Java 代码的一些技术的优缺点总结:

  • 简明语法充分利用对 Java 代码的熟悉,减少键入错误,使错误更少。
  • 切入点是一级实体,因此更容易对它们进行处理。
  • 对于许多开发人员,用 XML 进行声明性编程要比用 Java 语言扩展更熟悉。
  • 通知到切入点的绑定不能由开发人员控制。

如果这个小结仍然无法缩小决策范围,那么不要担心。除了用每种风格编写这些方面的感觉之外,还有更多需要考虑的东西。当在下一节中查看语义的时候,语法决策还会出现,而且也会影响在第 2 部分中讨论的工具支持。

语义的相似性
虽然工具的方面声明风格之间存在主要的语法差异,但是核心的 AOP 语义是类似的。每个工具都有完全相同的连接点模型的概念,都把连接点作为 Java 程序中的关键点,把切入点作为匹配连接点的机制,把通知作为指定连接点匹配时执行操作的机制。

表 3表 4 总结了每种技术的语义。您可以注意到,命令规范上有许多微小的差异和变化,但是各种技术最终聚合在相同的核心概念上。这种聚合有很大的好处,因为这意味着学习曲线很容易从一项 AOP 技术转移到另外一项 AOP 技术。剩下来要考虑的就是每种技术的差异所带来的优劣了。

回到连接点
一个 AOP 工具连接点模型的表达方式决定了可用的连接点粒度,以及连接点如何匹配。每个 AOP 工具都提供了大量用于连接点匹配的原生切入点。有些原生切入点只与特定类型的连接点匹配(例如,方法执行)。其他切入点能够根据连接点的公共属性(例如,在某个控制流程中的所有连接点)匹配任何类型的连接点。连接点的类型以及它们特定的切入点,可以分成以下几组:

  • 调用(Invocation)—— 调用或执行方法和其他代码元素时的点。

  • 初始化(Initialization)—— 初始化类和对象时的点。

  • 访问(Access)—— 读写某些字段时的点。

  • 异常处理(Exception handling)—— 抛出和处理异常与错误时的点。

另外,也支持以下没有类型的切入点分类:

  • 控制流程(Control flow)—— 在某个流程控制流程中的连接点。

  • 包含(Containment)—— 与包含在某个类或方法中的代码位置对应的连接点。

  • 条件(Conditional)—— 特定预测为真的连接点。

如表 3 所示,每个工具实现连接点模型的方式,以及它们用来匹配连接点的原生切入点,都略有差异。注意,在某些情况下(在括号中表示),连接点不用切入点标识。

表 3. 连接点和用来匹配连接点的原生切入点

要富于表现力还是要简单?
在这里主要的优劣在于富于表现力和简单性的比较。更加完整和精细的切入点集合允许通过方面访问程序执行中更多有趣的点。例如,与持久性有关的方面可能需要访问对象的初始化连接点。但是这类完整性也会带来额外的复杂性和更陡峭的学习曲线。许多 Java 程序员并不区分调用和执行,而且没有几个人需要理解初始化的微妙之处。而且许多常用的方面被当作是辅助性的,所以是否有表现力与应用程序的功能并没有紧密耦合。在常用的辅助性方面,例如监视和日志,通常只利用了粗粒度的切入点(例如方法执行)。从反面来看,更广泛的切入点集合确实具备量入为出的属性,因为切入点可以边用边学。如果不想用切入点制作程序,那么会造成面向对象代码的强制重构,例如:以 init() 方法的形式公开类的初始化。

AspectJ 和 AspectWerkz 的连接点模型差不多完全融合,而且已经成为最近的合并的关键促进者之一。JBoss AOP 模型几乎同样有表现力,只是为了简单性而遗漏了一些不太常用的连接点。一个明显的差异是:在 JBoss Aop 中,不能把控制流程表示成“在这个切入点的执行之下的所有连接点”。相反,程序员需要手动列出调用堆栈中的每个调用。

Spring AOP 采用了不同的技术,目的是限制它的连接点模型的表现力。这使它特别容易采用,而且对于一些粗粒度的横切很有用。即将发行的版本将与 AspectJ 集成,提供与精细横切机制的互操作性。

连接点模型的表现力与简单性的比较

一些项目可以从更有表现力的连接点模型(例如 AspectWerkz、AspectJ 和 JBoss AOP 提供的)获益,所以最好还是采用 Spring AOP 粗粒度的方便性?以下是更有表现力的模型固有优缺点的一个总结,多考虑一下这些方面会对您有所帮助:

  • 了解更多知识 。
  • 对于粗粒度的横切和辅助性方面,只需要很少的切入点。
  • 没有精细的切入点,许多方面就不能表达。
  • 使用新切入点的学习曲线是随用随学。

语言机制
我将用每种技术语言机制的详细对比结束 AOP 工具比较的第一部分的讨论。表 4 是 4 个工具的 AOP 语言的概括。下面讨论了最明显的区别。

表 4. 领先的 AOP 工具的语义概括

切入点匹配和复合:AspectJ、AspectWerkz 和 JBoss AOP 提供了类似的类型模式支持。它们三个都允许签名方面的匹配,对于 Java 5 应用程序来说,这些匹配包括注释和泛型。AspectJ 和 AspectWerkz 提供了一种简洁的引用多个类型的技术(例如 Account+ 表示帐户的所有子类型)。所有的工具都支持通配符匹配。Spring AOP 还提供了对正则表达式的支持。虽然这看起来可能是一个强大的优势,但还是要指出其他技术已经选择了放弃正则表达式,好让切入点读起来不是太难,同时不会存在潜在的损害。切入点复合操作符基本上都是相同的。Spring AOP 不提供“非”操作,这个操作通常与没有在 Spring AOP 连接点模型的容器(containment)连接点结合使用。

通知形式:AspectJ 支持比其他技术更多的通知形式,而 JBoss AOP 只支持一种通知形式。每种通知形式都可以表达成 around 通知,所以 JBoss 的技术是无限的,而且它确实提供了额外的简单性。不好的一面是它损失了简洁性,这一点可以从需要进行额外的调用才能继续执行原来的方法调用(如 图 4 所示)看得出来,而如果用 before 进行通知,这一点就是不必要的。还请注意,强迫通知去遵守普通的 Java 规则(就像注释和 XML 风格做的那样),在一些情况下容易出问题,因为这些规则是为方法设计的。AspectJ 拥有把被通知方法的异常“软化”的能力,这很有用,但是不符合方法异常检测的标准语义。

连接点上下文:在 AspectJ 和 AspectWerkz 中,通过指定和绑定切入点参数访问动态连接点的状态,类似于在 Java 语言中声明方法参数的技术(请参阅图 2图 3)。这为连接点上下文提供了静态类型化的好处。JBoss AOP 和 Spring AOP 反射性地访问连接点的状态,这消除了在切入点表达式中参数绑定的复杂性,代价是参数静态类型化。Java 程序员习惯了方法参数静态类型化带来的好处,同时还可以从切入点参数的静态类型化得到同样的好处。所以,在 JBoss AOP 最近的发行版本中,有提供静态类型化的“args” 的计划。

实例化:在所有的工具中,方面的实例化是由 per 子句控制的。正如所料,Spring AOP 的实例化模型更简单。对于额外的实例化机制的支持,则意味着可以把方面编写成只能应用于特定的动态上下文环境中,不用编写代码保存这个上下文并测试其他方面是否该应用这个方面。主要的区别因素是 AspectJ 支持在每个控制流程进行方面初始化,AspectWerkz 支持每个线程的初始化,而 JBoss 则支持每个连接点的初始化。哪种最有用则取决于具体的需求。

扩展性:方面的扩展性支持库方面的部署,这样可以在日后为特定程序而将这些库方面具体化。例如,一个方面库可以提供应用程序监视需要的全部逻辑和基础设施。但是,要采用某个特定项目的库,那么库使用的切入点必须扩展成应用程序特定的连接点。AspectJ 用抽象方面支持扩展性,抽象方面包含抽象的切入点和具体的通知。扩展抽象方面的子方面必须具体化切入点。AspectWerkz 和 JBoss AOP 使用了完全不同的技术,没有使用抽象切入点机制。扩展是通过生成方面的子类、并在 XML 中或通过注释定义新的通知绑定而实现的。切入点到通知的显式绑定为 AspectWerkz 和 JBoss AOP 提供了显著优势,从而可以很容易地把方面扩展到新系统,无需要生成子类。方面库的使用数据正在日益增多,这些将决定与其他技术使用的 Java 风格的继承和切入点绑定相比,AspectJ 特殊的 AOP 继承形式是更好还是更差。

每项技术在处理 AOP 的语言机制时,都提供了自己独特的优缺点。用一个简单的列表来总结这些优缺点是不可能的,因为对于不同的项目,每项技术的好处是各不相同的。但是,以上信息为选择工具或者遇到关键问题时寻找替代品提供了指南。

结束语
为项目选择一个 AOP 工具所面临的难题在于比较每种工具的优劣,同时不要让自己迷失其中。AOP工具比较的第一部分强调了 4 种领先的 AOP 技术的核心机制,并对比了它们的相似与不同之处。

如果本文是在十年之前报道一项新的模块化技术,那么我们可能就此打住,开始用自己选择的风格来编写方面 —— 可能是在命令行用 Emacs 或其他文本编辑器构建。但是今天,如果没有深入研究一项新技术如何与现有的开发环境和其他工具集成,人们是不会轻易地考虑采用它的。

所以,本文的第二部分把重点放在集成因素对 AOP工具选择的影响。在其他因素之中,将讨论每个工具如何处理方面的编译与设计,以及如何依据 IDE 集成与工具支持将它们都组合在一起。我还会比较这些工具的基本特性,看看它们背后到底是什么,包括进一步探讨 AspectJ 与 AspectWerkz 项目合并之后我们可以期盼从中得到什么。

参考资料

关于作者
Mik Kersten 是一流的面向方面的编程专家,也是 AspectJ 和 AJDT eclipse.org 项目的参与者。作为 Xerox PARC 的研究科学家,他为 AspectJ 构建了 IDE 支持。他正在不列颠哥伦比亚大学攻读博士学位,他的主要工作是使 IDE 更加面向方面。他也向构建开发工具的公司提供咨询,帮助公司利用、支持面向方面的编程技术。

posted on 2005-03-13 16:18 jinfeng_wang 阅读(1046) 评论(0)  编辑  收藏 所属分类: ZZAOP

只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问