This article was translated from the blog Comparing Spring AOP and AspectJ
introduce
There are multiple AOP libraries available today, and these components need to answer a number of questions:
- Is it compatible with my existing applications?
- Where do I implement AOP?
- Is integration fast into my application?
- What is the performance cost?
In this article, we’ll focus on answering these questions and introduce two of Java’s most popular AOP frameworks: Spring AOP and AspectJ.
AOP concepts
Before we begin, let’s do a quick, high-level review of terminology and core concepts:
- Aspect Aspect: A standard code/function that is distributed across multiple locations in an application, often different from the actual business logic (such as transaction management). Each facet focuses on a specific crosscutting function.
- Joinpoint: This is a specific point in program execution, such as method execution, function creation, or field assignment.
- Advice: Action taken by an aspect at a join point
- Pointcut: A regular expression that matches join points. Whenever any join point matches a pointcut, the specified advice associated with that pointcut is executed.
- Weaving: The process of linking cuts and target objects to create a notification object.
Spring AOP and AspectJ
Now, let’s discuss Spring AOP and AspectJ across multiple metrics such as capabilities and goals, weaving, internal structure, join points, and simplicity.
Capabilities and Goals
In short, Spring AOP and AspectJ have different goals. Spring AOP aims to provide a simple AOP implementation through Spring IoC that addresses the most common problems faced by coders. This is not a complete AOP solution, and it only works with Spring container-managed Beans.
AspectJ, on the other hand, is the original AOP implementation technology, providing an AOP solution for playing with this. AspectJ is more robust and complex than Spring AOP. It is worth noting that AspectJ can be applied to all domain objects.
Weaving
AspectJ and Spring AOP use different ways of weaving, which affects their behavior in terms of performance and ease of use. AspectJ uses three different types of weaving:
- Compile-time weaving: The AspectJ compiler loads both the source code for our facets and our application, and generates a woven class file as output.
- Compile weaving: This is known as binary weaving. It is used to weave existing class files and JAR files into our facets.
- Load-time weaving: This is exactly the same as binary weaving before, except that weaving is delayed until the class loader loads the class into the JVM.
For more information about AspectJ, see Head on Over to this article.
AspectJ uses compile-time and class-time weaving, while Spring AOP leverages runtime weaving.
Runtime weaving, which compiles these facets when the application executes using the target object’s proxy (using JDK dynamic proxy or CGLIB proxy).
Internal Structure and Application
Spring AOP is a proxy-based AOP framework. This means that to implement the cut of the target object, a proxy class for the target object is created. This can be done in two ways:
- JDK dynamic Proxies: Spring AOP’s preferred approach. JDK dynamic proxies are used every time the target object implements an interface.
- CGLIB proxy: If the target object does not implement an interface, the CGLIB proxy can be used.
You can learn more about Spring AOP at the official website. AspectJ, on the other hand, does nothing at runtime; classes and facets are compiled directly. Therefore, unlike Spring AOP, it does not require any design patterns. Weaving aspects into the code introduces its own compilation period, called AspectJ Compiler (AJC). With it, we compile the application and then run it by providing a small (<100K) runtime library.
Joinpoints
In the previous section, we introduced Spring AOP based on the proxy pattern. Therefore, it requires a subclass of the target class and applies crosscutting concerns accordingly. However, with limitations, we cannot apply crosscutting concerns (or facets) across “final” classes, because they cannot be overridden, resulting in runtime exceptions.
Likewise, this cannot be applied to static and final methods. Spring facets cannot be applied to them because they cannot be overridden. Therefore, Spring AOP only supports join points that execute methods because of these limitations. However, AspectJ weaves crosscutting concerns directly into the actual code before running. Unlike Spring AOP, it does not need to inherit target objects, and therefore supports many other join points as well. AspectJ supports the following join points:
It is also worth noting that in Spring AOP, aspects do not apply to methods called in the same class. It is obvious that when we call a method in the same class, we are not calling the Spring AOP provided proxy method. If we need this functionality, we can define a separate method in different Beans, or use AspectJ.
Simplicity
Spring AOP is significantly simpler because it does not introduce any additional compile time or weaving at compile time. It uses a run-time weaving approach and therefore seamlessly integrates our normal build process. As simple as it may seem, Spring AOP only works on Spring-managed Beans.
However, with AspectJ, we need to introduce an AJC compiler and repackage all our libraries (unless we switch to compile or load-time weaving). This approach is more complex than the previous one because it introduces AspectJ Java tools (including compilers (AJC), debuggers (AJDB), document generators (AJDoc), program structure browsers (AjBrowser)) that we need to integrate with the IDE or build tools.
Performance
Compile-time weaving is much faster than runtime weaving for performance reasons. Spring AOP is a proxy-based framework, so the application runs with proxy object generation for the target class. In addition, there are several method calls per aspect, which can have an impact on performance.
AspectJ differs from Spring AOP in that aspects are woven into the code before application execution, with no additional runtime overhead.
For these reasons, AspectJ has been tested to be about 8 to 35 times faster than Spring AOP. benchmarks
contrast
This quick table summarizes the main differences between Spring AOP and AspectJ:
Choose the right frame
If we analyze all the arguments in this section, we begin to understand that no one frame is absolutely better than another. In short, choice largely depends on our needs:
- Frameworks: If the application does not use the Spring framework, then we have no choice but to abandon the idea of using Spring AOP because it cannot manage anything outside the scope of the Spring container. However, if our application is created entirely using the Spring framework, we can use Spring AOP because it is straightforward to learn and apply.
- Flexibility: Spring AOP is not a complete AOP solution given its limited join point support, but it addresses the most common problems programmers face. If we want to dig deeper and leverage AOP to its fullest extent, and want support from the various join points available, AspectJ is the best choice.
- Performance: If we use a limited number of facets, the performance difference is minimal. However, sometimes applications have tens of thousands of facets. In this case, we don’t want to use runtime weaving, so AspectJ is the best choice. AspectJ is known to be 8 to 35 times faster than Spring AOP.
- Common advantage: The two frameworks are fully compatible. We can always take advantage of Spring AOP and still use AspectJ to get join points that the former does not support.
conclusion
In this article, we examine several key aspects of Spring AOP and AspectJ. We compared the flexibility of both approaches and how well they fit into our application.