选择使用哪种AOP声明风格
一旦你决定某种方式是实现特定需求的最佳途径,那么在Spring AOP和AspectJ之间、在Aspect语言(代码)风格、@AspectJ注解风格以及Spring XML风格之间该如何做出选择呢?这些决策受到多种因素的影响,包括应用需求、开发工具以及团队对AOP的熟悉程度。
Spring AOP还是Full AspectJ?
使用最简单且能满足需求的方法。Spring AOP比使用完整的AspectJ更为简单,因为无需在开发及构建过程中引入AspectJ编译器/织入器。如果你只需要对Spring Bean的操作执行进行拦截(建议),那么Spring AOP就是合适的选择。但如果你需要拦截非Spring容器管理的对象(通常是领域对象),就必须使用AspectJ。此外,如果你还想拦截除了简单方法执行之外的其他连接点(例如字段的getter或setter操作等),同样也需要使用AspectJ。
当你使用AspectJ时,你可以选择AspectJ语言语法(也称为“代码风格”)或@AspectJ注解风格。如果方面(aspects)在你的设计中扮演重要角色,并且你能够使用Eclipse的AspectJ开发工具(AJDT)插件,那么AspectJ语言语法是更优选的选择。这种语法更加清晰简洁,因为它是专门为编写方面而设计的。如果你不使用Eclipse,或者只有少数方面在应用程序中不起主要作用,那么你可能会考虑使用@AspectJ风格,在IDE中继续使用常规的Java编译方式,并在构建脚本中添加一个方面编织(aspect weaving)阶段。
使用@AspectJ还是XML进行Spring AOP?
如果你选择使用Spring AOP,那么你可以选择@AspectJ或XML风格。这里有各种需要考虑的权衡因素。
XML风格可能对现有的Spring用户来说最为熟悉,而且它是由真正的POJO(Plain Old Java Object)支持的。当使用AOP作为配置企业服务的工具时,XML可以是一个不错的选择(一个很好的判断标准是,你是否认为切点表达式是配置中的一部分,而你可能希望独立地对其进行修改)。通过XML风格,从配置中可以更清楚地了解系统中存在哪些组件或功能。
XML风格有两个缺点。首先,它不能将所解决的需求实现完全封装在单一的地方。DRY(Don’t Repeat Yourself)原则指出,系统中的任何知识都应该有唯一、明确、权威的表示形式。使用XML风格时,需求如何实现的细节分散在后台Bean类的声明和配置文件中的XML代码中。而使用@AspectJ风格时,这些信息被封装在单个模块——切面(aspect)中。其次,XML风格在表达能力上比@AspectJ风格稍显有限:它只支持“单例”(singleton)类型的切面实例化模型,并且无法组合在XML中声明的命名切点(pointcuts)。例如,在@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风格中,你可以声明前两个切点(pointcuts):
<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风格。