选择要使用的 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 注解风格。如果切面在您的设计中扮演重要角色,并且您能够使用 Eclipse 的 AspectJ Development Tools (AJDT) 插件,那么 AspectJ 语言语法是首选选项。它更清晰、更简单,因为该语言是专门为编写切面而设计的。如果您不使用 Eclipse,或者只有少数切面在您的应用程序中不扮演主要角色,您可能需要考虑使用 @AspectJ 风格,坚持在 IDE 中进行常规 Java 编译,并在构建脚本中添加切面织入阶段。

Spring AOP 使用 @AspectJ 还是 XML?

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

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

XML 风格有两个缺点。首先,它不能将它所解决的需求的实现完全封装在一个地方。DRY 原则指出,系统中任何知识都应该有一个单一、明确、权威的表示。当使用 XML 风格时,关于需求如何实现的知识被分散在支持 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 风格用于自定义切面,而不是简单的企业服务配置。