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 方法的灵活性以及它们与我们的应用程序的配合程度。

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