Choosing which AOP Declaration Style to Use

应用程序要求:AspectJ 适用于通知 Spring 外部对象和更高级别的连接点。

开发工具:AspectJ 语言语法更简洁,需要 AspectJ 开发工具支持。

团队 AOP 经验:Spring XML 样式可能更熟悉,但 @AspectJ 样式提供更好的封装和灵活性。

最终,@AspectJ 样式通常是首选,因为它提供了模块化、更好的切点组合和与 AspectJ 的兼容性。

一旦你决定针对给定的需求实现一个切面是最佳方法,你如何在 Spring AOP 与 AspectJ 之间做出决定,以及在 Aspect 语言(代码)样式、@AspectJ 注解样式或 Spring XML 样式之间做出决定?这些决定会受到多种因素的影响,包括应用程序要求、开发工具以及团队对 AOP 的熟悉程度。

Spring AOP or Full AspectJ?

使用最简单、可行的选择。Spring AOP 比使用完整的 AspectJ 更简单,因为无需将 AspectJ 编译器/织入引入你的开发和构建过程中。如果你只需要通知在 Spring Bean 上执行操作,Spring AOP 是正确的选择。如果你需要通知 Spring 容器未管理的对象(比如典型的域对象),你需要使用 AspectJ。如果你希望通知简单的执行方法以外的连接点(例如字段 get 或 set 连接点等等),也需要使用 AspectJ。

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

@AspectJ or XML for Spring AOP?

如果你选择使用 Spring AOP,则可以使用 @AspectJ 或 XML 样式。需要考虑各种取舍。

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

XML 样式有两个缺点。首先,它没有将对需求的实现 完全封装在同一地点。DRY 原则表明,系统内的任何知识片段应该有单独、明确、权威的表示形式。使用 XML 样式时,有关如何实现需求的知识分布在后端 bean 类的声明和配置文件中的 XML 中。使用 @AspectJ 样式时,此信息封装在一个模块中:方面。其次,XML 样式在表达功能上略受限制,因为它仅支持“单例”方面实例化模型,并且无法结合在 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 样式用于自定义切面,而不是简单的企业服务配置。