|
对于最新稳定版本,请使用 Spring Framework 7.0.6! |
AOP 概念
首先,我们来定义一些核心的AOP概念和术语。这些术语并非Spring所特有。不幸的是,AOP的术语并不是特别直观。然而,如果Spring使用自己的术语,反而会造成更大的混淆。
-
切面(Aspect):对横切多个类的关注点进行模块化。 事务管理是企业级 Java 应用中横切关注点的一个典型示例。 在 Spring AOP 中,切面通过使用普通类(基于 schema 的方式)或使用
@Aspect注解标注的普通类(@AspectJ 风格)来实现。 -
连接点(Join point):程序执行过程中的一个点,例如方法的执行或异常的处理。在 Spring AOP 中,连接点始终代表方法的执行。
-
通知(Advice):切面在特定连接点(join point)所采取的操作。不同类型的通知包括“环绕”(around)、“前置”(before)和“后置”(after)通知。(通知类型将在后文讨论。)包括 Spring 在内的许多 AOP 框架都将通知建模为拦截器(interceptor),并在连接点周围维护一个拦截器链。
-
切入点(Pointcut):一种匹配连接点(join points)的谓词。通知(Advice)与切入点表达式相关联,并在任何被该切入点匹配的连接点处执行(例如,执行某个特定名称的方法)。通过切入点表达式来匹配连接点这一概念是面向切面编程(AOP)的核心,Spring 默认使用 AspectJ 的切入点表达式语言。
-
引言:代表某个类型声明额外的方法或字段。Spring AOP 允许你向任何被通知(advised)的对象引入新的接口(以及相应的实现)。例如,你可以使用引入(introduction)使一个 Bean 实现
IsModified接口,以简化缓存操作。(在 AspectJ 社区中,这种引入被称为类型间声明(inter-type declaration)。) -
目标对象:被一个或多个切面所通知的对象。也称为“被通知对象”。由于 Spring AOP 是通过运行时代理实现的,因此该对象始终是一个代理对象。
-
AOP代理:由AOP框架创建的对象,用于实现切面契约(例如拦截方法执行等)。在Spring框架中,AOP代理是JDK动态代理或CGLIB代理。
-
织入(Weaving):将切面与其他应用程序类型或对象链接起来以创建一个被通知(advised)的对象。这可以在编译时(例如使用 AspectJ 编译器)、类加载时或运行时完成。Spring AOP 与其他纯 Java AOP 框架一样,在运行时执行织入。
Spring AOP 包含以下几种通知类型:
-
前置通知(Before advice):在连接点之前执行的通知,但不具备阻止执行流程继续到达该连接点的能力(除非它抛出异常)。
-
返回后通知(After returning advice):在连接点正常完成后执行的通知(例如,方法返回时未抛出异常)。
-
异常抛出后通知(After throwing advice):当方法因抛出异常而退出时执行的通知。
-
后置(最终)通知:无论连接点以何种方式退出(正常返回或异常返回),都会执行的通知。
-
环绕通知(Around advice):一种包围连接点(例如方法调用)的通知。 这是功能最强大的通知类型。环绕通知可以在方法调用前后执行自定义行为。 它还负责决定是否继续执行连接点,或者通过返回自己的返回值或抛出异常来直接结束被通知方法的执行。
环绕通知(Around advice)是最通用的通知类型。由于 Spring AOP 和 AspectJ 一样,提供了完整范围的通知类型,我们建议您使用能够实现所需行为的最弱(即最具体、限制性最强)的通知类型。例如,如果您仅需使用方法的返回值来更新缓存,那么实现一个返回后通知(after returning advice)会比使用环绕通知更为合适,尽管环绕通知也能完成同样的功能。使用最具体的通知类型可以提供更简单的编程模型,并减少出错的可能性。例如,您无需在用于环绕通知的 proceed() 上调用 JoinPoint 方法,因此也就不会因忘记调用它而导致错误。
所有通知参数都是静态类型的,因此您可以使用适当类型的通知参数(例如方法执行的返回值类型),而不是 Object 数组。
切入点(pointcut)所匹配的连接点(join point)这一概念是 AOP 的核心,它使 AOP 有别于仅提供拦截功能的早期技术。切入点使得通知(advice)能够独立于面向对象的继承层次结构进行目标定位。例如,你可以将一个提供声明式事务管理的环绕通知(around advice)应用到跨越多个对象的一组方法上(例如服务层中的所有业务操作)。