AOP概念

让我们从定义一些核心的AOP概念和术语开始。这些术语并非Spring特有。不幸的是,AOP术语并不特别直观。然而,如果Spring使用自己的术语,会更加令人困惑。

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

  • 连接点(Join point):程序执行过程中的一个点,例如方法的执行或异常的处理。在Spring AOP中,连接点始终代表方法的执行。

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

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

  • 引入(Introduction):代表类型声明附加方法或字段。Spring AOP允许您向任何受通知对象引入新接口(以及相应的实现)。例如,您可以使用引入使一个bean实现一个IsModified接口,以简化缓存。引入在AspectJ社区中被称为“inter-type声明”。

  • 目标对象(Target object):被一个或多个切面通知的对象。也称为“受通知对象”。由于Spring AOP是通过使用运行时代理实现的,因此该对象始终是一个代理对象。

  • AOP代理(AOP proxy):AOP框架创建的对象,用于实现切面合同(例如通知方法执行等)。在Spring框架中,AOP代理是JDK动态代理或CGLIB代理。

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

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

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

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

  • 抛出后通知(After throwing advice):如果方法通过抛出异常退出,则运行的通知。

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

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

环绕通知是最通用的通知类型。由于Spring AOP和AspectJ提供了全面的通知类型,我们建议您使用最不强大的通知类型来实现所需的行为。例如,如果您只需要使用方法的返回值更新缓存,最好实现一个返回后通知而不是环绕通知,尽管环绕通知也可以实现相同的功能。使用最具体的通知类型提供了一个更简单的编程模型,减少了错误的可能性。例如,您不需要在环绕通知中调用JoinPoint上的proceed()方法,因此不会忘记调用它。

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

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