选择使用哪种 AOP 声明风格

一旦您决定面向切面编程是实现特定需求的最佳方法,您该如何在使用 Spring AOP 或 AspectJ 以及在面向切面语言(代码)风格、@AspectJ 注解风格或 Spring XML 风格之间做出选择呢?这些决定会受到多种因素的影响,包括应用程序需求、开发工具以及团队对 AOP 的熟悉程度。

Spring AOP 还是完整的 AspectJ?

使用最简单的可行方法。Spring AOP 比使用完整的 AspectJ 更简单,因为它不需要将 AspectJ 编译器/织入器引入您的开发和构建流程。如果您只需要对 Spring Bean 上的操作执行通知,那么 Spring AOP 是正确的选择。如果您需要对 Spring 容器未管理的对象(例如域对象,通常)进行通知,则需要使用 AspectJ。如果您希望对除简单方法执行之外的其他连接点进行通知(例如,字段获取或设置连接点等),也需要使用 AspectJ。

当您使用 AspectJ 时,您可以选择 AspectJ 语言语法(也称为“代码风格”)或 @AspectJ 注解风格。如果面向切面在您的设计中扮演重要角色,并且您可以使用 AspectJ 开发工具 (AJDT) 的 Eclipse 插件,那么 AspectJ 语言语法是首选。它更简洁、更简单,因为该语言是专门为编写面向切面而设计的。如果您不使用 Eclipse 或只有几个在应用程序中不扮演主要角色的面向切面,您可能希望考虑使用 @AspectJ 风格,坚持在您的 IDE 中进行常规的 Java 编译,并在您的构建脚本中添加一个面向切面织入阶段。

@AspectJ 还是 Spring AOP 的 XML?

如果您选择使用 Spring AOP,您可以选择 @AspectJ 或 XML 风格。需要考虑各种权衡。

XML 风格可能对现有的 Spring 用户来说最熟悉,并且它由真正的 POJO 支持。当使用 AOP 作为配置企业服务的工具时,XML 是一个不错的选择(一个好的测试是您是否认为切点表达式是您可能希望独立更改的配置的一部分)。使用 XML 风格,从您的配置中可以更清楚地看到系统中存在哪些面向切面。

XML 风格的 AOP 存在两个缺点。首先,它没有将解决特定需求的实现完全封装在一个地方。DRY 原则指出,系统中任何知识都应该有一个单一、明确、权威的表示。使用 XML 风格时,关于如何实现需求的知识分散在 backing bean 类声明和配置文件中的 XML 之间。使用 @AspectJ 风格时,这些信息被封装在一个模块中:切面。其次,XML 风格在表达能力方面比 @AspectJ 风格略逊一筹:它只支持“单例”切面实例化模型,并且无法组合在 XML 中声明的命名切点。例如,在 @AspectJ 风格中,你可以编写以下代码

  • Java

  • Kotlin

@Pointcut("execution(* get*())")
public void propertyAccess() {}

@Pointcut("execution(com.xyz.Account+ *(..))")
public void operationReturningAnAccount() {}

@Pointcut("propertyAccess() && operationReturningAnAccount()")
public void accountPropertyAccess() {}
@Pointcut("execution(* get*())")
fun propertyAccess() {}

@Pointcut("execution(com.xyz.Account+ *(..))")
fun operationReturningAnAccount() {}

@Pointcut("propertyAccess() && operationReturningAnAccount()")
fun accountPropertyAccess() {}

在 XML 风格中,你可以声明前两个切点

<aop:pointcut id="propertyAccess"
		expression="execution(* get*())"/>

<aop:pointcut id="operationReturningAnAccount"
		expression="execution(com.xyz.Account+ *(..))"/>

XML 方法的缺点是,你无法通过组合这些定义来定义 `accountPropertyAccess` 切点。

@AspectJ 风格支持额外的实例化模型和更丰富的切点组合。它具有将切面作为模块化单元的优势。它还具有 @AspectJ 切面可以被 Spring AOP 和 AspectJ 理解(因此可以被使用)的优势。因此,如果你以后决定需要 AspectJ 的功能来实现额外的需求,你可以轻松地迁移到经典的 AspectJ 设置。总的来说,Spring 团队更喜欢 @AspectJ 风格来实现自定义切面,而不是简单地配置企业服务。