1. 概述

本文主要说明AOP的概念。

内容主要来Spring framework的官方文档

2 什么是AOP

面向方面的编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象的编程(OOP)。OOP中模块化的关键单元是类,而在AOP中模块化是切面。切面使关注点(例如事务管理)的模块化跨越了多种类型和对象。

Spring的关键组件之一是AOP框架。虽然Spring IoC容器不依赖于AOP,但AOP是对Spring IoC的补充,以提供功能强大的中间件解决方案。

Spring AOP与AspectJ切点

Spring提供了使用基于模式的方法或@Aspectj注释样式来编写自定义切面。这两种风格都提供了完整类型的通知,并可以在使用Spring AOP进行编织的同时使用AspectJ切点注释。

AOP在Spring框架中主要用于:

  • 提供声明式企业服务。此类服务中主要是声明式事务管理。

  • 让用户实现自定义切面,以通过AOP补充其对OOP的使用。

3. AOP的概念

让我们首先定义一些核心的AOP概念和术语。

这些术语并非特定于Spring。不过,AOP术语并不是特别直观。

而且,在Spring中使用自己的术语,会更加令人感到困惑。

  • 切面(Aspect):跨越多个类的模块化关注点。

    事务管理是企业Java应用程序中横切关注点的一个很好的例子。

    在SpringAOP中,切面是通过使用常规类(基于模式的方法)或使用@Aspect注释注解的常规类来实现的。

  • 连接点(Join point):程序执行过程中的一点,如方法的执行或异常的处理。

    在SpringAOP中,连接点总是表示一个方法执行

  • 通知(Advice):一个切面在特定的连接点采取的处理。

    通知的类型包括环绕通知。

    许多AOP框架(包括Spring)将通知建模为拦截器,并在连接点周围维护拦截器链。

  • 切点(Pointcut):与连接点匹配的谓词。

    通知与切入点表达式关联,并在与切入点匹配的任何连接点上执行,比如,使用特定名称执行方法。

    切点表达式匹配的连接点概念是AOP的核心,Spring默认使用AspectJ切点表达式语言。

  • 引入(Introduction):代表类型声明其他方法或字段。

    Spring AOP允许你向任何通知对象引入新的接口和相应的实现。

    比如,你可以使用一个说明使bean实现一个IsModified接口,以简化缓存。

    引入在AspectJ社区中称为类型间声明。

  • 目标对象(Target object):织入 advice 的目标对象。也被称为advised object

    Spring AOP是通过使用运行时代理实现的,所以目标对象始终是一个代理对象。

  • AOP代理:一个类被 AOP 框架织入 advice, 产生的结果类, 它是融合了原类和增强逻辑的代理类.

    在Spring AOP中,AOP代理通常是JDK动态代理对象或CGLIB代理对象。

  • 织入(Weaving):将切面与其他应用程序类型或对象链接起来,并创建目标对象。

    根据不同的实现, AOP织入有三种:

    • 编译时织入,需要使用特殊的编译器。比如AspectJ编译器。
    • 类加载时织入, 需要使用特殊的类装载器。
    • 动态代理织入, 在运行时为目标类添加通知生成子类的方式.

4. Sping AOP的通知类型

Spring AOP包含以下几种通知类型:

  • Before advice: 在连接点之前执行。但不能阻止执行到连接点,除非我们的Before advice通知代码中抛出异常。

  • After returning advice: 在连接点正常完成返回后执行,比如,一个方法正常执行并返回,注意这里不能发生异常。

  • After throwing advice: 如果连接点执行并发生异常而退出,则执行这个通知。

  • After (finally) advice: 无论连接点执行是否发生异常,都会执行的通知。

  • Around advice: 在连接点执行之前和执行之后都会执行的通知。

    这是是最常用的的通知。可以在方法调用前后执行自定义行为。

Around advice是最最常用的通知。

由于Spring AOP和AspectJ都提供了一系列完整的通知类型,

建议你使用功能相对最弱的通知类型来实现所需的行为。

比如,如果只需要使用方法的返回值来更新缓存,那么最好实现After returning advice ,而不是使用Around advice,虽然Around advice可以完成相同的事情。但是使用最具体的通知类型会提供了一个更简单的编程模型,并且发生错误的可能性更小。

比如,你不能在用Around advice的连接点前后调用proceed()方法,如果使用After returning advice,就不会发生错误调用的BUG。

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

切点匹配的连接点概念是AOP的关键,它将AOP与只提供拦截的旧技术区分开来。

切点使通知能够独立于面向对象的层次结构作为目标。

例如,你可以将一个Around advice应用到一组跨越多个对象的方法(例如服务层中的所有业务操作)上,从而提供声明性事务管理。

5. 总结

在本文中,我们说明了AOP的一些概念,以及Spring AOP的通知类型。