AOP原理及应用

什么是 AOP?

Spring AOP(Aspect-Oriented Programming)是Spring框架提供的一种面向切面编程的技术。它通过将横切关注点(例如日志记录、事务管理、安全性检查等)从主业务逻辑代码中分离出来,以模块化的方式实现对这些关注点的管理和重用。

在Spring AOP中,切面(Aspect)是一个模块化的关注点,它可以跨越多个对象,例如日志记录、事务管理等。切面通过定义切点(Pointcut)和增强(Advice)来介入目标对象的方法执行过程。

切点是一个表达式,用于匹配目标对象的一组方法,在这些方法执行时切面会被触发。增强则定义了切面在目标对象方法执行前、执行后或抛出异常时所要执行的逻辑。

Spring AOP通过使用动态代理技术,在目标对象方法执行时将切面的逻辑织入到目标对象的方法中。这样,我们可以在不修改原始业务代码的情况下,实现横切关注点的统一处理。

总而言之,Spring AOP是一种通过切面将横切关注点模块化的技术,它提供了一种简洁的方式来管理和重用跨越多个对象的关注点逻辑。

AOP 的优点

  1. 模块化:Spring AOP将横切关注点从主业务逻辑代码中分离出来,以模块化的方式实现对这些关注点的管理和重用。这样,我们可以更容易地维护代码,并且可以将同一个关注点的逻辑应用到多个方法或类中。

  2. 非侵入式:使用Spring AOP时,我们不需要修改原始业务逻辑代码,只需要在切点和增强中定义我们所需要的逻辑即可。这样,我们可以保持原始代码的简洁性和可读性。

  3. 可重用性:我们可以将同一个切面应用于多个目标对象进行横切处理。这样,我们可以提高代码的重用性,并且可以更加方便地维护和更新切面逻辑。

  4. 松耦合:AOP可以减少各个业务模块之间的耦合度,这是因为我们可以将某些通用的逻辑作为切面来实现,而不是直接在各个业务模块中实现。这样可以使得各个业务模块之间更加独立,从而提高代码的可维护性。

AOP 的核心概念

  1. 切面(Aspect):切面是增强和切点的结合,增强和切点共同定义了切面的全部内容。

多个切面之间的执行顺序如何控制?首先要明确,在“进入”连接点的情况下,最高优先级的增强会先执行;在“退出”连接点的情况下,最高优先级的增强会最后执行。

1.通常使用@Order 注解直接定义切面顺序

2.实现Ordered 接口重写 getOrder 方法。Ordered.getValue()方法返回值(或者注解值)较低的那个有更高的优先级。

  1. 连接点(Join point):一般指方法,在Spring AOP中,一个连接点总是代表一个方法的执行。连接点是方法调用或者方法执行时的某个特定时刻(如方法调用、异常抛出等)。

  2. 增强(或称为通知)(Advice):在AOP术语中,切面的工作被称为增强。知实际上是程序运行时要通过Spring AOP框架来触发的代码段。

    1. 前置增强(Before):在目标方法被调用之前调用增强功能;

    2. 后置增强(After):在目标方法完成之后调用增强,此时不会关心方法的输出是什么;

    3. 返回增强(After-returning ):在目标方法成功执行之后调用增强;

    4. 异常增强(After-throwing):在目标方法抛出异常后调用增强;

    5. 环绕增强(Around):增强包裹了被增强的方法,在被增强的方法调用之前和调用之后执行自定义的逻辑

  3. 切点(Pointcut):一个切点是一个表达式,它用来匹配哪些连接点需要被切面所增强。切点可以通过注解、正则表达式、逻辑运算等方式来定义。以AspectJ举例,说白了就可以理解为是execution表达式。

  4. 引入(Introduction):引入允许我们向现有类添加新方法或属性。 在AOP中表示为干什么(引入什么);

  5. 目标对象(Target Object): 被一个或者多个切面(aspect)所增强(advise)的对象。它通常是一个代理对象。

  6. 织入(Weaving):织入是把切面应用到目标对象并创建新的代理对象的过程。在AOP中表示为怎么实现的;织入分为编译期织入、类加载期织入、运行期织入;SpringAOP是在运行期织入。

Spring AOP JDK动态代理与CGlib动态代理区别

Spring AOP 支持两种类型的动态代理:JDK 动态代理和 CGLIB 动态代理。它们之间有以下区别:

  • 基于类型:JDK 动态代理是基于接口的代理,而 CGLIB 动态代理是基于类的代理。

  • 代理对象创建:JDK 动态代理通过 Java 自带的 java.lang.reflect.Proxy 创建代理对象,该对象必须实现一个或多个接口。CGLIB 动态代理通过字节码生成技术创建代理对象,无需目标类实现接口,直接继承目标类。

  • 性能:JDK 动态代理在运行时需要使用反射,导致较低的性能。CGLIB 动态代理通过生成字节码,避免了反射,因此通常比 JDK 动态代理速度更快。

  • 对象类型:JDK 动态代理只能代理具有接口的目标对象,不适用于没有接口的类。CGLIB 动态代理可以代理任何类,包括没有实现接口的类。

  • 继承:JDK 动态代理只能代理目标对象的接口方法,不能代理其父类中的方法。CGLIB 动态代理可以代理目标类及其父类中的方法。

Spring AOP 与 AspectJ AOP有什么区别

Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。

如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比 Spring AOP 快很多。

AOP 与 OOP 区别

二者都是面向对象编程的范式,但它们关注的角度不同。下面是它们之间的区别:

  • 技术视角:OOP 是一种代码组织技术,它通过将数据和操作封装在对象中来实现模块化和复用。AOP 是一种编程范式,它允许开发者在执行过程中(而非编译期)动态地添加、删除或修改代码的功能。

  • 关注点:OOP 关注对象的内部结构和行为,其目标是更好地描述和设计一个系统的真实世界概念。AOP 关注横切关注点(Cross-cutting Concerns),即存在于应用程序各个层面的相同问题,如日志、事务、安全等。

  • 实现方式:OOP 是通过类和接口来实现封装、继承和多态等特性,使得类能够更好地表达问题领域内的概念。AOP 是通过将通用功能抽取为切面(Aspect),并与核心业务逻辑混合使用,来实现这些横切关注点。

  • 关注点分离:OOP 面对复杂系统可能导致代码重复或紧密耦合的问题,而 AOP 采用横切关注点的方式来解决这些问题,使得系统功能更加组合和重用。

OOP 不能很好地处理一些分散在多个类或对象中的公共行为(如日志记录、事务管理、权限控制、接口限流、接口幂等等),这些行为通常被称为 横切关注点(cross-cutting concerns) 。如果我们在每个类或对象中都重复实现这些行为,那么会导致代码的冗余、复杂和难以维护。AOP 可以将横切关注点(如日志记录、事务管理、权限控制、接口限流、接口幂等等)从 核心业务逻辑(core concerns,核心关注点) 中分离出来,实现关注点的分离。

基本代码使用

本文参考:Spring AOP 详细深入讲解+代码示例


AOP原理及应用
http://bloomivy.github.io/2025/02/05/AOP原理及应用/
作者
Bloom
发布于
2025年2月5日
许可协议