AOP Concepts

让我们从定义一些主要的 AOP 概念和术语开始。这些术语不特定于 Spring。遗憾的是,AOP 术语并不特别直观。然而,如果 Spring 使用自己的术语,那就更令人困惑了。

  • 切面:一个跨越多个类的关注点的模块化。事务管理是企业 Java 应用程序中横切关注点的典例。在 Spring AOP 中,切面是通过使用常规类(schema-based approach)或注释了 @Aspect 注释的常规类(@AspectJ style)来实现的。

  • 连接点:程序执行期间某一时刻,例如方法的执行或异常的处理。在 Spring AOP 中,连接点始终表示方法执行。

  • 建议:切面在特定连接点上执行的操作。不同类型的建议包括“around”、“before”和“after”建议。(建议类型将在后面讨论。)许多 AOP 框架(包括 Spring)将建议建模为拦截器,并在连接点周围维护一个拦截器链。

  • 切入点:与连接点匹配的谓词。建议与切入点表达式关联,并在切入点表达式匹配的任何连接点上运行(例如,执行具有特定名称的方法)。由切入点表达式匹配连接点这一概念是 AOP 的核心,Spring 默认使用 AspectJ 切入点表达式语言。

  • 引介:代表类型声明附加方法或字段。Spring AOP 允许您向任何建议的对象引入新接口(及其对应的实现)。例如,您可以使用引介,使 bean 实现 IsModified 接口,以简化缓存。(在 AspectJ 社区中,引介被称为类型间声明。)

  • 目标对象:正在被一个或多个切面建议的对象。也称为“建议对象”。由于 Spring AOP 是通过使用运行时代理实现的,因此此对象始终是一个代理对象。

  • AOP 代理:AOP 框架创建的对象,用于实现切面契约(建议方法执行等)。在 Spring 框架中,AOP 代理是 JDK 动态代理或 CGLIB 代理。

  • 编织:将切面与其他应用程序类型或对象链接起来,以创建建议对象。这可以在编译时(例如,使用 AspectJ 编译器)、加载时或运行时完成。Spring AOP(与其他纯 Java AOP 框架一样)在运行时执行编织。

Spring AOP 包括以下类型的通知:

  • Before 建议:在连接点之前运行的建议,但它无法阻止执行流继续到该连接点(除非抛出异常)。

  • After 返回建议:在连接点正常完成之后运行的建议(例如,如果方法返回而不抛出异常)。

  • After 抛出建议:在方法通过抛出异常而退出时运行的建议。

  • After(finaly)建议:无论连接点退出方式(正常或异常返回)如何,都要运行的建议。

  • Around 建议:环绕连接点(如方法调用)的建议。这是建议中最强大的类型。Around 建议可以在方法调用之前和之后执行自定义行为。它还负责选择继续到连接点,还是通过返回自己的返回值或抛出异常来捷径建议的方法执行。

Around 通知是最通用的通知类型。由于 Spring AOP 与 AspectJ 一样提供了全系列的通知类型,我们建议你使用可实现所需行为的最不强大的通知类型。例如,如果你只需要使用一个方法的返回值更新一个缓存,那么你最好实现一个 after-returning 通知,而不是一个 around 通知,尽管一个 around 通知也可以实现相同的事情。使用最具体的通知类型提供了一个更简单的编程模型,并且出错的可能性更小。例如,你不需要对用于 around 通知的 JoinPoint 调用 proceed() 方法,因此,你无法调用它。

所有通知参数都是静态类型的,因此你可以使用适当类型(例如,方法执行的返回值类型)的通知参数,而不是 Object 数组。

匹配切点的连接点概念是 AOP 的关键,它区别于仅提供拦截的旧技术。切点使通知能够独立于面向对象层次结构进行定位。例如,你可以应用一个提供声明式事务管理的 around 通知,该通知跨越多个对象(比如服务层中的所有业务操作)的一组方法。