1. Introduction
1.介绍
There are multiple available AOP libraries today, and these need to be able to answer a number of questions:
今天有多种可用的AOP库,这些库需要能够回答一些问题。
- Is it compatible with my existing or new application?
- Where can I implement AOP?
- How quickly will it integrate with my application?
- What is the performance overhead?
In this article, we’ll look at answering these questions and introduce Spring AOP and AspectJ – the two most popular AOP frameworks for Java.
在这篇文章中,我们将着眼于回答这些问题,并介绍Spring AOP和AspectJ–两个最流行的Java AOP框架。
2. AOP Concepts
2.AOP概念
Before we begin, let’s do a quick, high-level review of terms and core concepts:
在我们开始之前,让我们对术语和核心概念做一个快速、高水平的回顾。
- Aspect – a standard code/feature that is scattered across multiple places in the application and is typically different than the actual Business Logic (for example, Transaction management). Each aspect focuses on a specific cross-cutting functionality
- Joinpoint – it’s a particular point during execution of programs like method execution, constructor call, or field assignment
- Advice – the action taken by the aspect in a specific joinpoint
- Pointcut – a regular expression that matches a joinpoint. Each time any join point matches a pointcut, a specified advice associated with that pointcut is executed
- Weaving – the process of linking aspects with targeted objects to create an advised object
3. Spring AOP and AspectJ
3.Spring AOP和AspectJ
Now, let’s discuss Spring AOP and AspectJ across a number of axis – such as capabilities, goals, weaving, internal structure, joinpoints, and simplicity.
现在,我们来讨论一下Spring AOP和AspectJ的一些轴心–如能力、目标、编织、内部结构、连接点和简单性。
3.1. Capabilities and Goals
3.1.能力和目标
Simply put, Spring AOP and AspectJ have different goals.
简单地说,Spring AOP和AspectJ有不同的目标。
Spring AOP aims to provide a simple AOP implementation across Spring IoC to solve the most common problems that programmers face. It is not intended as a complete AOP solution – it can only be applied to beans that are managed by a Spring container.
Spring AOP旨在提供一个跨Spring IoC的简单AOP实现,以解决程序员面临的最常见的问题。它并不打算作为一个完整的AOP解决方案 – 它只能应用于由Spring容器管理的Bean。
On the other hand, AspectJ is the original AOP technology which aims to provide complete AOP solution. It is more robust but also significantly more complicated than Spring AOP. It’s also worth noting that AspectJ can be applied across all domain objects.
另一方面,AspectJ是最初的AOP技术,旨在提供完整的AOP解决方案。它更强大,但也明显比Spring AOP复杂。另外值得注意的是,AspectJ可以应用于所有领域对象。
3.2. Weaving
3.2.编织
Both AspectJ and Spring AOP uses the different type of weaving which affects their behavior regarding performance and ease of use.
AspectJ和Spring AOP都使用了不同类型的编织,这影响了它们在性能和易用性方面的行为。
AspectJ makes use of three different types of weaving:
AspectJ使用了三种不同类型的编织。
- Compile-time weaving: The AspectJ compiler takes as input both the source code of our aspect and our application and produces a woven class files as output
- Post-compile weaving: This is also known as binary weaving. It is used to weave existing class files and JAR files with our aspects
- Load-time weaving: This is exactly like the former binary weaving, with a difference that weaving is postponed until a class loader loads the class files to the JVM
For more in-depth information on AspectJ itself, head on over to this article.
有关AspectJ本身的更多深入信息,请参见前往该文章。
As AspectJ uses compile time and classload time weaving, Spring AOP makes use of runtime weaving.
由于AspectJ使用编译时间和类加载时间编织,Spring AOP利用了运行时间编织。
With runtime weaving, the aspects are woven during the execution of the application using proxies of the targeted object – using either JDK dynamic proxy or CGLIB proxy (which are discussed in next point):
在运行时编织中,使用目标对象的代理–使用JDK动态代理或CGLIB代理(将在下一步讨论),在应用程序的执行过程中编织各个方面。
3.3. Internal Structure and Application
3.3.内部结构和应用
Spring AOP is a proxy-based AOP framework. This means that to implement aspects to the target objects, it’ll create proxies of that object. This is achieved using either of two ways:
Spring AOP是一个基于代理的AOP框架。这意味着,为了实现目标对象的各个方面,它将创建该对象的代理。这是用两种方式中的一种实现的。
- JDK dynamic proxy – the preferred way for Spring AOP. Whenever the targeted object implements even one interface, then JDK dynamic proxy will be used
- CGLIB proxy – if the target object doesn’t implement an interface, then CGLIB proxy can be used
We can learn more about Spring AOP proxying mechanisms from the official docs.
我们可以从官方文档中了解更多关于Spring AOP代理机制的信息。
AspectJ, on the other hand, doesn’t do anything at runtime as the classes are compiled directly with aspects.
另一方面,AspectJ在运行时不做任何事情,因为类是直接用aspects编译的。
And so unlike Spring AOP, it doesn’t require any design patterns. To weave the aspects to the code, it introduces its compiler known as AspectJ compiler (ajc), through which we compile our program and then runs it by supplying a small (< 100K) runtime library.
因此,与Spring AOP不同,它不需要任何设计模式。为了将各个方面编织到代码中,它引入了被称为AspectJ编译器(ajc)的编译器,通过它我们可以编译我们的程序,然后通过提供一个小的(<100K)运行时库来运行它。
3.4. Joinpoints
3.4.连接点
In section 3.3, we showed that Spring AOP is based on proxy patterns. Because of this, it needs to subclass the targeted Java class and apply cross-cutting concerns accordingly.
在3.3节中,我们表明Spring AOP是基于代理模式的。正因为如此,它需要对目标Java类进行子类化,并相应地应用跨领域的关注。
But it comes with a limitation. We cannot apply cross-cutting concerns (or aspects) across classes that are “final” because they cannot be overridden and thus it would result in a runtime exception.
但是它有一个限制。我们不能在 “final “类之间应用交叉关注(或方面),因为它们不能被重写,因此会导致运行时异常。
The same applies for static and final methods. Spring aspects cannot be applied to them because they cannot be overridden. Hence Spring AOP because of these limitations, only supports method execution join points.
这同样适用于静态和最终方法。Spring方面不能应用于它们,因为它们不能被重写。因此,Spring AOP因为有这些限制,只支持方法执行的连接点。
However, AspectJ weaves the cross-cutting concerns directly into the actual code before runtime. Unlike Spring AOP, it doesn’t require to subclass the targetted object and thus supports many others joinpoints as well. Following is the summary of supported joinpoints:
然而,AspectJ在运行前将交叉关注点直接编织到实际代码中。与Spring AOP不同,它不需要对目标对象进行子类化,因此也支持许多其他连接点。以下是所支持的连接点的摘要。
Joinpoint | Spring AOP Supported | AspectJ Supported |
---|---|---|
Method Call | No | Yes |
Method Execution | Yes | Yes |
Constructor Call | No | Yes |
Constructor Execution | No | Yes |
Static initializer execution | No | Yes |
Object initialization | No | Yes |
Field reference | No | Yes |
Field assignment | No | Yes |
Handler execution | No | Yes |
Advice execution | No | Yes |
It’s also worth noting that in Spring AOP, aspects aren’t applied to the method called within the same class.
还值得注意的是,在Spring AOP中,方面并不应用于同一类中调用的方法。
That’s obviously because when we call a method within the same class, then we aren’t calling the method of the proxy that Spring AOP supplies. If we need this functionality, then we do have to define a separate method in different beans, or use AspectJ.
这显然是因为当我们在同一个类中调用一个方法时,那么我们并没有调用Spring AOP提供的代理的方法。如果我们需要这个功能,那么我们确实必须在不同的Bean中定义一个单独的方法,或者使用AspectJ。
3.5. Simplicity
3.5.简单性
Spring AOP is obviously simpler because it doesn’t introduce any extra compiler or weaver between our build process. It uses runtime weaving, and therefore it integrates seamlessly with our usual build process. Although it looks simple, it only works with beans that are managed by Spring.
Spring AOP显然更简单,因为它没有在我们的构建过程中引入任何额外的编译器或编织器。它使用运行时编织,因此它与我们通常的构建过程无缝集成。虽然它看起来很简单,但它只适用于由Spring管理的bean。
However, to use AspectJ, we’re required to introduce the AspectJ compiler (ajc) and re-package all our libraries (unless we switch to post-compile or load-time weaving).
然而,为了使用AspectJ,我们需要引入AspectJ编译器(ajc)并重新打包我们所有的库(除非我们改用后编译或加载时编织)。
This is, of course, more complicated than the former – because it introduces AspectJ Java Tools (which include a compiler (ajc), a debugger (ajdb), a documentation generator (ajdoc), a program structure browser (ajbrowser)) which we need to integrate with either our IDE or the build tool.
当然,这比前者更复杂–因为它引入了AspectJ Java工具(包括一个编译器(ajc)、一个调试器(ajdb)、一个文档生成器(ajdoc)、一个程序结构浏览器(ajbrowser)),我们需要将其与我们的IDE或构建工具集成。
3.6. Performance
3.6.性能
As far as performance is concerned, compile-time weaving is much faster than runtime weaving. Spring AOP is a proxy-based framework, so there is the creation of proxies at the time of application startup. Also, there are a few more method invocations per aspect, which affects the performance negatively.
就性能而言,编译时织入比运行时织入快得多。Spring AOP是一个基于代理的框架,所以在应用启动时需要创建代理。另外,每个方面有更多的方法调用,这对性能有负面的影响。
On the other hand, AspectJ weaves the aspects into the main code before the application executes and thus there’s no additional runtime overhead, unlike Spring AOP.
另一方面,AspectJ在应用程序执行之前就将各个方面编织到主代码中,因此没有额外的运行时开销,这与Spring AOP不同。
For these reasons, the benchmarks suggest that AspectJ is almost around 8 to 35 times faster than Spring AOP.
由于这些原因,基准测试表明,AspectJ几乎比Spring AOP快8到35倍左右。
4. Summary
4.总结
This quick table summarizes the key differences between Spring AOP and AspectJ:
这个快速表格总结了Spring AOP和AspectJ的主要区别。
Spring AOP | AspectJ |
---|---|
Implemented in pure Java | Implemented using extensions of Java programming language |
No need for separate compilation process | Needs AspectJ compiler (ajc) unless LTW is set up |
Only runtime weaving is available | Runtime weaving is not available. Supports compile-time, post-compile, and load-time Weaving |
Less Powerful – only supports method level weaving | More Powerful – can weave fields, methods, constructors, static initializers, final class/methods, etc… |
Can only be implemented on beans managed by Spring container | Can be implemented on all domain objects |
Supports only method execution pointcuts | Support all pointcuts |
Proxies are created of targeted objects, and aspects are applied on these proxies | Aspects are weaved directly into code before application is executed (before runtime) |
Much slower than AspectJ | Better Performance |
Easy to learn and apply | Comparatively more complicated than Spring AOP |
5. Choosing the Right Framework
5.选择正确的框架
If we analyze all the arguments made in this section, we’ll start to understand that it’s not at all that one framework is better than another.
如果我们分析一下本节中的所有论点,我们就会开始明白,根本不是一个框架比另一个框架好。
Simply put, the choice heavily depends on our requirements:
简单地说,选择在很大程度上取决于我们的要求。
- Framework: If the application is not using Spring framework, then we have no option but to drop the idea of using Spring AOP because it cannot manage anything that’s outside the reach of spring container. However, if our application is created entirely using Spring framework, then we can use Spring AOP as it’s straightforward to learn and apply
- Flexibility: Given the limited joinpoint support, Spring AOP is not a complete AOP solution, but it solves the most common problems that programmers face. Although if we want to dig deeper and exploit AOP to its maximum capability and want the support from a wide range of available joinpoints, then AspectJ is the choice
- Performance: If we’re using limited aspects, then there are trivial performance differences. But there are sometimes cases when an application has more than tens of thousands of aspects. We would not want to use runtime weaving in such cases so it would be better to opt for AspectJ. AspectJ is known to be 8 to 35 times faster than Spring AOP
- Best of Both: Both of these frameworks are fully compatible with each other. We can always take advantage of Spring AOP whenever possible and still use AspectJ to get support of joinpoints that aren’t supported by the former
6. Conclusion
6.结论
In this article, we analyzed both Spring AOP and AspectJ, in several key areas.
在这篇文章中,我们对Spring AOP和AspectJ,在几个关键领域进行了分析。
We compared the two approaches to AOP both on flexibility as well as on how easily they will fit with our application.
我们比较了这两种AOP方法的灵活性,以及它们与我们的应用的契合程度。