AOP 概念

让我们从定义一些 AOP 的核心概念和术语开始。这些术语并非 Spring 特有的。不幸的是,AOP 术语并不特别直观。但是,如果 Spring 使用它自己的术语,将会更加混乱。

  • 方面:跨越多个类的关注点模块化。事务管理是企业 Java 应用程序中跨领域关注点的一个很好的例子。在 Spring AOP 中,方面是通过使用普通类(基于模式的方法)或使用 @Aspect 注解的普通类(@AspectJ 风格)来实现的。

  • 连接点:程序执行过程中的一个点,例如方法的执行或异常的处理。在 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 包括以下类型的通知

  • 前置通知:在连接点之前运行的通知,但没有能力阻止执行流程继续进行到连接点(除非它抛出异常)。

  • 后置返回通知:在连接点正常完成之后运行的通知(例如,如果方法在不抛出异常的情况下返回)。

  • 抛出异常后通知:在方法通过抛出异常退出时运行的通知。

  • 最终通知(finally):无论连接点以何种方式退出(正常或异常返回),都将运行的通知。

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

环绕通知是最通用的通知类型。由于 Spring AOP 与 AspectJ 一样,提供了全面的通知类型,我们建议您使用能够实现所需行为的最低效的通知类型。例如,如果您只需要使用方法的返回值更新缓存,那么最好实现一个返回后通知,而不是环绕通知,尽管环绕通知可以完成相同的事情。使用最具体的通知类型提供了一个更简单的编程模型,并且错误的可能性更小。例如,您不需要在用于环绕通知的 JoinPoint 上调用 proceed() 方法,因此您无法调用它。

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

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