|
对于最新稳定版本,请使用 Spring Framework 7.0.6! |
选择使用哪种 AOP 声明风格
一旦你确定使用切面(aspect)是实现某个需求的最佳方式,那么接下来该如何在 Spring AOP 和 AspectJ 之间进行选择,以及在 Aspect 语言(代码)风格、@AspectJ 注解风格和 Spring XML 风格之间做出决定呢?这些决策受到多种因素的影响,包括应用需求、开发工具以及团队对 AOP 的熟悉程度。
Spring AOP 还是完整的 AspectJ?
使用能够满足需求的最简单方案。Spring AOP 比完整的 AspectJ 更简单,因为无需在开发和构建过程中引入 AspectJ 编译器或织入器(weaver)。如果你仅需对 Spring Bean 中的操作执行进行通知(advice),那么 Spring AOP 是合适的选择。但如果你需要对非 Spring 容器管理的对象(例如典型的领域对象)进行通知,则必须使用 AspectJ。此外,如果你希望通知的连接点(join point)不仅仅是简单的方法执行(例如字段的读取或设置等连接点),你也需要使用 AspectJ。
当你使用 AspectJ 时,可以选择 AspectJ 语言语法(也称为“代码风格”)或 @AspectJ 注解风格。如果你的设计中切面(aspects)扮演着重要角色,并且你能够使用 Eclipse 的 AspectJ 开发工具(AJDT) 插件,那么 AspectJ 语言语法是首选方案。这种语法更加简洁清晰,因为该语言本身就是专门为编写切面而设计的。如果你不使用 Eclipse,或者你的应用中只有少量切面且它们并不起主要作用,那么你可以考虑使用 @AspectJ 风格,在 IDE 中继续使用常规的 Java 编译方式,并在构建脚本中添加一个切面织入(aspect weaving)阶段。
Spring AOP:选择 @AspectJ 还是 XML?
如果你选择使用 Spring AOP,你可以选择 @AspectJ 风格或 XML 风格。 需要考虑各种权衡因素。
XML 风格对现有的 Spring 用户来说可能最为熟悉,并且它基于真正的 POJO。当将 AOP 用作配置企业服务的工具时,XML 可能是一个不错的选择(一个很好的判断标准是:你是否认为切入点表达式是你配置的一部分,并且可能需要独立进行修改)。使用 XML 风格时,从配置中可以更清晰地看出系统中存在哪些切面。
XML 风格存在两个缺点。首先,它无法将所处理需求的实现完全封装在单一位置。DRY(Don't Repeat Yourself)原则指出,系统中的任何知识都应当有且仅有一个明确、权威的表示。使用 XML 风格时,关于如何实现某个需求的知识被分散到了后备 bean 类的声明和配置文件中的 XML 配置两处。而当你使用 @AspectJ 风格时,这些信息会被封装在一个单独的模块中:即切面(aspect)。其次,XML 风格在表达能力上略逊于 @AspectJ 风格:它仅支持“singleton”(单例)切面实例化模型,并且无法组合在 XML 中声明的具名切入点(named pointcut)。例如,在 @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 风格支持额外的实例化模型和更丰富的切入点(pointcut)组合。它的优势在于将切面保持为一个模块化单元。此外,@AspectJ 切面既可以被 Spring AOP 理解(并使用),也可以被 AspectJ 理解(并使用)。因此,如果你日后决定需要利用 AspectJ 的能力来实现更多需求,可以轻松迁移到经典的 AspectJ 设置。通常情况下,Spring 团队更倾向于在企业服务的简单配置之外,对自定义切面采用 @AspectJ 风格。