Spring AOP 和 AspectJ 的比较

简介: Spring AOP 和 AspectJ 的比较

一、简介

如今有多个可用的 AOP 库,这些库需要能够回答许多问题:

  • 它与我现有的或新的应用程序兼容吗?
  • 哪里可以实现AOP?
  • 它与我的应用程序集成的速度有多快?
  • 性能开销是多少?

在本文中,我们将回答这些问题并介绍 Spring AOP 和 AspectJ——两个最流行的 Java AOP 框架。

2.AOP概

在开始之前,让我们对术语和核心概念进行快速、高层次的回顾:

  • 方面 – 分散在应用程序中多个位置的标准代码/功能,通常与实际业务逻辑(例如事务管理)不同。每个方面都侧重于特定的横切功能
  • 连接点——它是程序执行过程中的一个特定点,例如方法执行、构造函数调用或字段赋值
  • 建议 – 方面在特定连接点采取的操作
  • 切入点——匹配连接点的正则表达式。每次任何连接点与切入点匹配时,都会执行与该切入点关联的指定建议
  • 编织——将方面与目标对象链接起来以创建建议对象的过程

3. Spring AOP和AspectJ现在,让我们从多个方面来讨论 Spring AOP 和 AspectJ,例如功能、目标、编织、内部结构、连接点和简单性。

3.1. 能力和目标

简单地说,Spring AOP 和 AspectJ 有不同的目标。

Spring AOP 旨在提供跨 Spring IoC 的简单 AOP 实现,以解决程序员面临的最常见问题。它并不是一个完整的 AOP 解决方案——它只能应用于由 Spring 容器管理的 bean。

另一方面,AspectJ是原始的AOP技术,旨在提供完整的AOP解决方案。它比 Spring AOP 更健壮,但也复杂得多。还值得注意的是,AspectJ 可以应用于所有域对象。

3.2. 编织

AspectJ 和 Spring AOP 都使用不同类型的编织,这会影响它们在性能和易用性方面的行为。

AspectJ 使用三种不同类型的编织:

  1. 编译时编织:AspectJ 编译器将方面和应用程序的源代码作为输入,并生成编织类文件作为输出
  2. 编译后编织:这也称为二进制编织。它用于将现有的类文件和 JAR 文件与我们的方面编织在一起
  3. 加载时编织:这与之前的二进制编织完全相同,不同之处在于编织被推迟,直到类加载器将类文件加载到 JVM

有关 AspectJ 本身的更多深入信息,请阅读本文

正如 AspectJ 使用编译时和类加载时编织一样,Spring AOP 使用运行时编织

通过运行时编织,各个方面在应用程序执行期间使用目标对象的代理进行编织 - 使用 JDK 动态代理或 CGLIB 代理(在下一点中讨论):

3.3. 内部结构及应用

Spring AOP是一个基于代理的AOP框架。这意味着要实现目标对象的方面,它将创建该对象的代理。这是通过以下两种方式之一实现的:

  1. JDK动态代理——Spring AOP的首选方式。每当目标对象实现一个接口时,就会使用 JDK 动态代理
  2. CGLIB代理——如果目标对象没有实现接口,则可以使用CGLIB代理

我们可以从官方文档中了解更多关于Spring AOP代理机制的信息

另一方面,AspectJ 在运行时不执行任何操作,因为类是直接使用方面编译的。

因此与 Spring AOP 不同,它不需要任何设计模式。为了将方面编织到代码中,它引入了称为 AspectJ 编译器 (ajc) 的编译器,通过它我们可以编译程序,然后通过提供一个小型(< 100K)运行时库来运行它。

3.4. 连接点

在3.3节中,我们展示了Spring AOP是基于代理模式的。因此,它需要对目标 Java 类进行子类化并相应地应用横切关注点。

但它有一个限制。我们不能在“最终”类之间应用横切关注点(或方面),因为它们无法被覆盖,因此会导致运行时异常。

这同样适用于静态和最终方法。Spring 方面不能应用于它们,因为它们不能被覆盖。因此,Spring AOP 由于这些限制,仅支持方法执行连接点。

然而,AspectJ 在运行之前将横切关注点直接编织到实际代码中。与 Spring AOP 不同,它不需要子类化目标对象,因此也支持许多其他连接点。以下是支持的连接点的摘要:

连接点 Spring AOP 支持 支持 AspectJ
方法调用 是的
方法执行 是的 是的
构造函数调用 是的
构造函数执行 是的
静态初始化器执行 是的
对象初始化 是的
现场参考 是的
现场作业 是的
处理程序执行 是的
建议执行 是的

还值得注意的是,在 Spring AOP 中,方面并不应用于同一类中调用的方法。

这显然是因为当我们调用同一个类中的方法时,我们并没有调用 Spring AOP 提供的代理的方法。如果我们需要这个功能,那么我们必须在不同的bean中定义一个单独的方法,或者使用AspectJ。

3.5. 简单

Spring AOP 显然更简单,因为它没有在我们的构建过程之间引入任何额外的编译器或编织器。它使用运行时编织,因此它与我们通常的构建过程无缝集成。虽然它看起来很简单,但它只适用于由 Spring 管理的 bean。

但是,要使用 AspectJ,我们需要引入 AspectJ 编译器 (ajc) 并重新打包所有库(除非我们切换到编译后或加载时编织)。

当然,这比前者更复杂——因为它引入了 AspectJ Java 工具(其中包括编译器(ajc)、调试器(ajdb)、文档生成器(ajdoc)、程序结构浏览器(ajbrowser))需要与我们的 IDE 或构建工具集成。

3.6. 表现就性能而言,编译时编织比运行时编织快得多Spring AOP是一个基于代理的框架,因此在应用程序启动时会创建代理。此外,每个方面还有更多的方法调用,这会对性能产生负面影响。

另一方面,AspectJ 在应用程序执行之前将方面编织到主代码中,因此与 Spring AOP 不同,没有额外的运行时开销。

由于这些原因,基准测试表明 AspectJ 几乎比 Spring AOP 快 8 到 35 倍。

4. 总结此快速表总结了 Spring AOP 和 AspectJ 之间的主要区别:

春季AOP 方面J
用纯Java实现 使用Java编程语言的扩展实现
无需单独的编译过程 需要 AspectJ 编译器 (ajc),除非设置了 LTW
仅运行时编织可用 运行时编织不可用。支持编译时、编译后和加载时 Weaving
功能较弱 – 仅支持方法级别编织 更强大——可以编织字段、方法、构造函数、静态初始化器、最终类/方法等……
只能在Spring容器管理的bean上实现 可以在所有域对象上实现
仅支持方法执行切入点 支持所有切入点
代理是由目标对象创建的,方面应用于这些代理 在执行应用程序之前(运行时之前),方面直接编织到代码中
比 AspectJ 慢很多 更好的性能
易于学习和应用 比 Spring AOP 相对复杂一些

5. 选择正确的框架如果我们分析本节中提出的所有论点,我们将开始理解,并不是一个框架就比另一个框架更好。

简而言之,选择很大程度上取决于我们的要求:

  • 框架:如果应用程序没有使用 Spring 框架,那么我们别无选择,只能放弃使用 Spring AOP 的想法,因为它无法管理 Spring 容器范围之外的任何内容。但是,如果我们的应用程序完全使用 Spring 框架创建,那么我们可以使用 Spring AOP,因为它易于学习和应用
  • 灵活性:鉴于有限的连接点支持,Spring AOP 不是一个完整的 AOP 解决方案,但它解决了程序员面临的最常见问题。尽管如果我们想要更深入地挖掘并最大限度地利用 AOP 并希望获得广泛的可用连接点的支持,那么 AspectJ 是您的选择
  • 性能:如果我们使用有限的方面,那么性能差异很小。但有时应用程序具有超过数万个方面的情况。在这种情况下,我们不想使用运行时编织,因此最好选择 AspectJ。已知 AspectJ 比 Spring AOP 快 8 到 35 倍
  • 两者的优点:这两个框架彼此完全兼容。我们总是可以尽可能利用 Spring AOP,并且仍然使用 AspectJ 来获得前者不支持的连接点的支持

六,结论在本文中,我们在几个关键领域分析了 Spring AOP 和 AspectJ。

我们比较了这两种 AOP 方法的灵活性以及它们与我们的应用程序的配合程度。

目录
相关文章
|
5月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
645 0
|
9月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
1419 13
|
4月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
6月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
625 6
|
6月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
939 25
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
527 24
|
11月前
|
Java API 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——Spring Boot 中的 AOP 处理
本文详细讲解了Spring Boot中的AOP(面向切面编程)处理方法。首先介绍如何引入AOP依赖,通过添加`spring-boot-starter-aop`实现。接着阐述了如何定义和实现AOP切面,包括常用注解如`@Aspect`、`@Pointcut`、`@Before`、`@After`、`@AfterReturning`和`@AfterThrowing`的使用场景与示例代码。通过这些注解,可以分别在方法执行前、后、返回时或抛出异常时插入自定义逻辑,从而实现功能增强或日志记录等操作。最后总结了AOP在实际项目中的重要作用,并提供了课程源码下载链接供进一步学习。
1533 0