一旦你决定切面是实现特定需求的最佳方法,你如何决定使用 Spring AOP 或 AspectJ,以及 Aspect 语言(代码)风格、@AspectJ 注解风格或 Spring XML 风格?这些决定受到很多因素的影响,包括应用需求、开发工具以及团队对 AOP 的熟悉程度。
Spring AOP 还是完整的 AspectJ?
使用最简单的东西就可以了。Spring AOP 比使用完整的 AspectJ 更简单,因为不需要在开发和构建过程中引入 AspectJ 编译器/编织器。如果你只需要 advice 执行 Spring Bean 上的操作,Spring AOP 是正确的选择。如果你需要 advice 不由 Spring 容器管理的对象(比如典型的域(domain)对象),你就需要使用 AspectJ。如果你想为简单的方法执行提供 advice,你也需要使用 AspectJ(例如,字段获取(get)或设置(set)等)。
当你使用 AspectJ 时,你可以选择 AspectJ 语言语法(也被称为 「代码风格」)或 @AspectJ
注解风格。很明显,如果你不使用 Java 5+,就已经为你做出了选择。使用代码风格。如果各个方面在你的设计中起着很大的作用,而且你能够使用 Eclipse 的 AspectJ 开发工具(AJDT)插件,那么 AspectJ 语言语法是首选。它更干净、更简单,因为该语言是专门为编写切面而设计的。 如果你不使用 Eclipse,或者只有几个切面在你的应用程序中不发挥主要作用的话,你可能要考虑使用 @AspectJ 风格,坚持在你的 IDE 中使用常规的 Java 编译,并在你的构建脚本中添加一个切面编织阶段。
Spring AOP的@AspectJ或XML?
如果你选择了使用 Spring AOP,你可以选择 @AspectJ 或 XML 风格。有各种权衡需要考虑。
XML 风格可能是现有 Spring 用户最熟悉的,而且它有真正的 POJO 支持。当把 AOP 作为配置企业服务的工具时,XML 可以是一个很好的选择(一个很好的检验标准是,你是否认为 pointcut 表达式是你可能想独立改变的配置的一部分)。通过 XML 风格,可以说从你的配置中可以更清楚地看到系统中存在哪些切面。
XML 风格有两个缺点:
- 首先,它没有将它所解决的需求的实现完全封装在一个地方。DRY 原则说,系统中的任何知识都应该有一个单一的、明确的、权威的表述。当使用 XML 风格时,关于如何实现需求的知识被分割成支持 bean 的声明和配置文件中的 XML。当你使用 @AspectJ 风格时,这些信息被封装在一个单一的模块中:切面。
- 其次,XML 风格比 @AspectJ 风格所能表达的内容稍有限制。只支持单例切面的实例化模型,而且不可能将 XML 中声明的命名的 pointcut 表达式结合起来。例如,在 @AspectJ 风格中,你可以写成下面这样的东西
@Pointcut("execution(* get*())")
public void propertyAccess() {}
@Pointcut("execution(org.xyz.Account+ *(..))")
public void operationReturningAnAccount() {}
@Pointcut("propertyAccess() && operationReturningAnAccount()")
public void accountPropertyAccess() {}
在XML样式中,你可以声明前两个 pointcut
<aop:pointcut id="propertyAccess"
expression="execution(* get*())"/>
<aop:pointcut id="operationReturningAnAccount"
expression="execution(org.xyz.Account+ *(..))"/>
XML 的缺点是,你不能通过组合这些定义来定义 accountPropertyAccess 这个切点
@AspectJ 风格支持额外的实例化模型和更丰富的 pointcut 组合。它的优点是将切面作为一个模块化的单元。它还有一个优点,就是@AspectJ 切面可以被 Spring AOP 和 AspectJ 理解(从而被消费)。因此,如果你后来决定需要 AspectJ 的能力来实现额外的需求,你可以轻松地迁移到经典的 AspectJ 设置。总的来说,Spring 团队更倾向于采用 @AspectJ 风格来实现超出企业服务简单配置的自定切面。