Spring AOP 与 AspectJ

Posted

技术标签:

【中文标题】Spring AOP 与 AspectJ【英文标题】:Spring AOP vs AspectJ 【发布时间】:2010-12-09 01:24:19 【问题描述】:

我的印象是 Spring AOP 最适合用于特定于应用程序的任务,例如安全、日志记录、事务等,因为它使用自定义 Java5 注释作为框架。然而,AspectJ 似乎对设计模式更友好。

谁能强调在 Spring 应用程序中使用 的各种优缺点?

【问题讨论】:

当一些注解存在于Spring中,但又存在于Java中,你应该使用什么?爪哇。相同的逻辑适用于此功能。春天就是春天。今天在这里,明天就走了。 (请记住人们在 Spring 之前使用 Struts 一段时间)。 AspectJ 是首选的长期解决方案。它会比春天更持久。我并没有拒绝 Spring,只是说,在这方面...... :-; 【参考方案1】:

与 AOP 相比,AspectJ 不需要在编译时增强目标类。相反,它会在运行时为目标类生成一个代理类,该代理类要么实现与目标类相同的接口,要么是目标类的子类。 总之,代理类的实例可以用作目标类的实例。一般来说,编译时增强的 AOP 框架在性能上更有优势——因为运行时增强的 AOP 框架每次运行都需要动态增强。

【讨论】:

【参考方案2】:

这个article也对这个话题有很好的解释。

Spring AOP 和 AspectJ 有不同的目标。

Spring AOP 旨在提供一个跨 Spring 的简单 AOP 实现 IoC 解决程序员面临的最常见问题。

另一方面,AspectJ 是原始的 AOP 技术,旨在 提供完整的AOP解决方案。

【讨论】:

【参考方案3】:

重要的是要考虑您的方面是否是关键任务以及您的代码部署在哪里。 Spring AOP 将意味着您依赖于加载时编织。这可能无法编织,并且根据我的经验,这意味着可能存在记录的错误,但不会阻止应用程序在没有方面代码的情况下运行并非如此;但我个人并不知道]。编译时编织避免了这种情况。

此外,如果您将 AspectJ 与 aspectj-maven-plugin 结合使用,那么您可以在 CI 环境中针对您的切面运行单元测试,并确信已构建的工件经过测试和正确编织。虽然您当然可以编写 Spring 驱动的单元测试,但您仍然无法保证部署的代码将是在 LTW 失败时测试过的代码。

另一个考虑因素是您是否将应用程序托管在能够直接监控服务器/应用程序启动成功或失败的环境中,或者您的应用程序是否部署在不受您监督的环境中[例如它由客户托管]。同样,这将为编译时间编织指明方向。

五年前,我更倾向于使用 Spring 配置的 AOP,原因很简单,因为它更易于使用并且不太可能破坏我的 IDE。然而,随着计算能力和可用内存的增加,这已不再是一个问题,基于我上面概述的原因,使用 aspectj-maven-plugin 的 CTW 已成为我工作环境中更好的选择。

【讨论】:

【参考方案4】:

Spring-AOP 优点

它比 AspectJ 更易于使用,因为您不必使用 LTW (load-time weaving) 或 AspectJ 编译器。

它使用代理模式和装饰器 模式

Spring-AOP 的缺点

这是基于代理的 AOP,所以基本上只能使用方法执行连接点。 在同一类中调用另一个方法时不应用方面。 可能会有一点运行时开销。 Spring-AOP 无法向不是由 Spring 工厂创建的任何内容添加方面

AspectJ 优点

这支持所有连接点。这意味着你可以做任何事情。 运行时开销比 Spring AOP 少。

AspectJ 缺点

小心。检查您的方面是否仅编织到您想要编织的内容。 您需要使用 AspectJ 编译器进行额外的构建过程,或者必须设置 LTW(加载时编织)

【讨论】:

@Configurable 需要通过 Spring 使用 AspecJ。来自文档:If you need to advise objects not managed by the Spring container (such as domain objects typically), then you will need to use AspectJ. 另一个 spring-aop 对我来说是由于基于代理的方法而无法读取的长堆栈跟踪 答案中令人困惑的部分:一个工具的专业人士有一点运行时开销,而另一个工具有一点运行时开销的可能性如何? @Moreaki:他说“有点开销”是一个骗局,“有点开销”是一个专业人士。单个“a”的区别非常重要——在英语中,“a little”表示“一些”,而“little”表示“几乎没有”。 只是一个简单的疑问-在您的 Spring AOP Pros 中(第 2 点)-如果我们在 Spring 中使用 @Aspect 注释,它将是 aspectJ AOP,只是想知道,在这种情况下它是否会使用 Proxy (运行时)或字节修改(编译时)。因为,我的印象是 AspectJ 是编译时,而 Spring AOP 是运行时 AOP。请帮忙【参考方案5】:

Spring AOP 是 Spring 框架的重要组成部分之一。在非常基础的阶段,spring 框架是基于 IoC 和 AOP 的。在 Spring 的官方课程中有一张幻灯片,上面写着:

AOP 是框架中最重要的部分之一。

理解 Spring 中的 AOP 如何工作的关键点是,当您使用 Spring 编写 Aspect 时,我们会为框架构建一个代理,如果您的 bean 实现了接口,则使用 JDKDynamicProxy;如果您的 bean 实现了接口,则使用 CGLIB bean 没有实现任何接口。请记住,如果您使用 Spring 3.2 之前的版本,则您的类路径中必须包含 cglib 2.2。从 Spring 3.2 开始它就没有用了,因为 cglib 2.2 包含在核心中。

创建 bean 时的框架将创建一个代理来包装您的对象并添加横切关注点职责,例如安全性、事务管理、日志记录等。

以这种方式创建的代理将应用于一个切入点表达式,该表达式对框架进行检测以决定将哪些 bean 和方法创建为代理。与您的代码相比,该建议将承担更多责任。请记住,在此过程中,切入点仅捕获未声明为 final 的公共方法。

现在,在 Spring AOP 中,Aspect 的编织将在容器启动时由容器执行,而在 AspectJ 中,您必须通过修改字节码对代码进行后编译来执行此操作。因此,在我看来,Spring 方法比 AspectJ 更简单、更易于管理。

另一方面,使用 Spring AOP,您无法使用 AOP 的全部功能,因为实现是通过代理完成的,而不是通过修改代码来完成的。

与在 AspectJ 中一样,您可以在 SpringAOP 中使用加载时编织。您可以在 spring 中使用代理和特殊配置、@EnabledLoadWeaving 或 XML 实现此功能。您可以使用名称空间作为示例。但是在 Spring AOP 中你不能拦截所有的情况。例如,Spring AOP 不支持 new 命令。

但是在 Spring AOP 中,您可以通过在 spring 配置 bean 中使用 aspectof 工厂方法从 AspectJ 的使用中受益。

由于 Spring AOP 基本上是从容器创建的代理,因此您只能将 AOP 用于 spring bean。在使用 AspectJ 时,您可以在所有 bean 中使用方面。另一个比较点是调试和代码行为的可预测性。使用 Spring AOP,这项工作全部由 Java 编译器执行,方面是为 Spring bean 创建代理的一种非常酷的方式。在 AspectJ 中,如果您修改代码,您需要更多的编译,并且要了解您的切面在哪里编织可能会很困难。即使在 spring 中关闭编织也更简单:使用 spring 从配置中删除方面,重新启动它就可以工作了。在 AspectJ 中你必须重新编译代码!

在加载时编织中,AspectJ 比 Spring 更灵活,因为 Spring 不支持 AspectJ 的所有选项。但在我看来,如果您想更改 bean 的创建过程,更好的方法是在工厂中管理自定义登录,而不是在加载时编织改变新操作员行为的方面。

希望这张AspectJ和Spring AOP的全景图能帮助你理解这两种药水的区别

【讨论】:

【参考方案6】:

除了其他人所说的 - 只是换个说法,there are two major differences

    一个与编织类型有关。 另一个连接点定义。

Spring-AOP:使用dynamic proxy if interface exists or cglib library if direct implementation provided.的概念通过代理编织运行时

AspectJ: 如果源可用,则通过AspectJ Java Tools(ajc compiler) 编译时间编织或编译后编织(使用已编译文件)。此外,可以启用 Spring 的加载时间编织 - 它需要 aspectj 定义文件并提供灵活性。

编译时编织可以提供性能优势(在某些情况下)以及joinpoint definition in Spring-aop is restricted to method definition only which is not the case for AspectJ.

【讨论】:

【参考方案7】:

附加说明:如果高负载下的性能很重要,您将需要比 Spring AOP 快 9-35 倍的 AspectJ。 10ns vs 355ns 听起来可能不多,但我见过人们使用很多方面。 10K的价值方面。在这些情况下,您的请求可能涉及数千个方面。在这种情况下,您将 ms 添加到该请求中。

请参阅benchmarks。

【讨论】:

基准web.archive.org/web/20150520175004/https://docs.codehaus.org/…【参考方案8】:

The spring user manual 会直接从马口中提供很多信息。

6.4 - Choosing which AOP declaration style to use 一章对你来说已经死了,因为它讨论了两者的优缺点。

段落6.1.2 - Spring AOP Capabilites and goals 和章节6.2 - @Aspect support 和6.8 - Using AspectJ with Spring applications 应该特别有趣。

【讨论】:

以上是关于Spring AOP 与 AspectJ的主要内容,如果未能解决你的问题,请参考以下文章

Spring框架第五篇之Spring与AOP

spring的aop实现与自定义Advisor

#yyds干货盘点# 老王读Spring AOP-4Spring AOP 与Spring IoC 结合的过程 && ProxyFactory 解析

spring-AOP原理与应用

Spring中AOP简介与使用

Spring框架学习AOP技术理解与使用