比较Spring AOP与AspectJ

本文翻译自博客Comparing Spring AOP and AspectJ程序员

介绍

现在有多个可用的AOP库,这些组件须要回答一系列的问题:web

  • 是否与我现有的应用兼容?
  • 我在哪实现AOP?
  • 集成到个人应用是否很快?
  • 性能开销是多少?

本文中,咱们将会着重回答这些问题,并介绍两款Java最流行的AOP框架:Spring AOP 和 AspectJ。正则表达式

AOP概念

在咱们开始以前,让咱们对术语和核心概念作一个快速,高水平的回顾:spring

  • Aspect切面:一个分布在应用程序中多个位置的标准代码/功能,一般与实际的业务逻辑(例如事务管理)不一样。 每一个切面都侧重于一个特定的横切功能。
  • Joinpoint链接点:这是程序执行中的特定点,如方法执行,构调用造函数或字段赋值等。
  • Advice通知:在一个链接点中,切面采起的行动
  • Pointcut切点:一个匹配链接点的正则表达式。 每当任何链接点匹配一个切入点时,就执行与该切入点相关联的指定通知。
  • Weaving织入:连接切面和目标对象来建立一个通知对象的过程。

Spring AOP and AspectJ

如今,一块儿来讨论Spring AOP and AspectJ,跨越多指标,如能力和目标、织入方式、内部结构、链接点和简单性。设计模式

Capabilities and Goals

简而言之,Spring AOP和AspectJ有不一样的目标。
Spring AOP旨在经过Spring IoC提供一个简单的AOP实现,以解决编码人员面临的最常出现的问题。这并非完整的AOP解决方案,它只能用于Spring容器管理的beans。浏览器

另外一方面,AspectJ是最原始的AOP实现技术,提供了玩这个的AOP解决方案。AspectJ更为健壮,相对于Spring AOP也显得更为复杂。值得注意的是,AspectJ可以被应用于全部的领域对象。微信

Weaving

AspectJ and Spring AOP使用了不一样的织入方式,这影响了他们在性能和易用性方面的行为。
AspectJ使用了三种不一样类型的织入:框架

  1. 编译时织入:AspectJ编译器同时加载咱们切面的源代码和咱们的应用程序,并生成一个织入后的类文件做为输出。
  2. 编译后织入:这就是所熟悉的二进制织入。它被用来编织现有的类文件和JAR文件与咱们的切面。
  3. 加载时织入:这和以前的二进制编织彻底同样,所不一样的是织入会被延后,直到类加载器将类加载到JVM。

更多关于AspectJ的信息,请见head on over to this article函数

AspectJ使用的是编译期和类加载时进行织入,Spring AOP利用的是运行时织入。工具

运行时织入,在使用目标对象的代理执行应用程序时,编译这些切面(使用JDK动态代理或者CGLIB代理)。

springaop-process
springaop-process

Internal Structure and Application

Spring AOP 是一个基于代理的AOP框架。这意味着,要实现目标对象的切面,将会建立目标对象的代理类。这能够经过下面两种方式实现:

  • JDK动态代理:Spring AOP的首选方法。 每当目标对象实现一个接口时,就会使用JDK动态代理。
  • CGLIB代理:若是目标对象没有实现接口,则可使用CGLIB代理。

关于Spring AOP能够经过官网了解更多。
另外一方面,AspectJ在运行时不作任何事情,类和切面是直接编译的。所以,不一样于Spring AOP,他不须要任何设计模式。织入切面到代码中,它引入了本身的编译期,称为AspectJ compiler (ajc)。经过它,咱们编译应用程序,而后经过提供一个小的(<100K)运行时库运行它。

Joinpoints

在上一小节,咱们介绍了Spring AOP基于代理模式。所以,它须要目标类的子类,并相应的应用横切关注点。可是也伴随着局限性,咱们不能跨越“final”的类来应用横切关注点(或切面),由于它们不能被覆盖,从而致使运行时异常。

一样地,也不能应用于静态和final的方法。因为不能覆写,Spring的切面不能应用于他们。所以,Spring AOP因为这些限制,只支持执行方法的链接点。
然而,AspectJ在运行前将横切关注点直接织入实际的代码中。 与Spring AOP不一样,它不须要继承目标对象,所以也支持其余许多链接点。AspectJ支持以下的链接点:

joinpoint
链接点支持

一样值得注意的是,在Spring AOP中,切面不适用于同一个类中调用的方法。这很显然,当咱们在同一个类中调用一个方法时,咱们并无调用Spring AOP提供的代理的方法。若是咱们须要这个功能,能够在不一样的beans中定义一个独立的方法,或者使用AspectJ。

Simplicity

Spring AOP显然更加简单,由于它没有引入任何额外的编译期或在编译期织入。它使用了运行期织入的方式,所以是无缝集成咱们一般的构建过程。尽管看起来很简单,Spring AOP只做用于Spring管理的beans 。

然而,使用AspectJ,咱们须要引入AJC编译器,从新打包全部库(除非咱们切换到编译后或加载时织入)。这种方式相对于前一种,更加复杂,由于它引入了咱们须要与IDE或构建工具集成的AspectJ Java工具(包括编译器(ajc),调试器(ajdb),文档生成器(ajdoc),程序结构浏览器(ajbrowser))。

Performance

考虑到性能问题,编译时织入比运行时织入快不少。Spring AOP是基于代理的框架,所以应用运行时会有目标类的代理对象生成。另外,每一个切面还有一些方法调用,这会对性能形成影响。

AspectJ不一样于Spring AOP,是在应用执行前织入切面到代码中,没有额外的运行时开销。

因为以上缘由,AspectJ通过测试大概8到35倍快于Spring AOP。benchmarks

对比

这个快速表总结了Spring AOP和AspectJ之间的主要区别:

com
对比

选择合适的框架

若是咱们分析本节全部的论点,咱们就会开始明白,没有绝对的一个框架比另外一个框架更好。
简而言之,选择很大程度上取决咱们的需求:

  • 框架:若是应用程序不使用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和AOP两种方法的灵活性,以及它们与咱们的应用程序的匹配程度。

订阅最新文章,欢迎关注个人公众号

微信公众号
相关文章
相关标签/搜索