选择使用哪种 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 Development Tools (AJDT) 的 Eclipse 插件,那么 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 风格。