Different Types of AspectJ Weaving
How each weaving types work, internally.
Join the DZone community and get the full member experience.
Join For Free
There are different types of weaving on AspectJ, I’m going to share the differences for each weaving type.
If you have grasped the basic concepts of AOP (moreover AspectJ) and want to know the details about different types of AspectJ weaving, which are Compile-time weaving, Post-compile (binary) weaving, and Load-time weaving, do continue reading this article.
Compile-time Weaving
xxxxxxxxxx
public class GdnBeforeAspect {
"execution(* greet(..))") (
public void beforeGreet(final JoinPoint joinPoint) {
doBefore(joinPoint);
}
private void doBefore(final JoinPoint joinPoint) {
System.out.println("[ASPECTJ BEFORE]");
System.out.println("Target class' name: " + joinPoint.getTarget().getClass());
System.out.println("Target method's name: " + joinPoint.getSignature().getName());
System.out.println("Target method's arguments: " + Arrays.toString(joinPoint.getArgs()));
System.out.println("[ASPECTJ BEFORE]");
}
}
Those 2 code snippets are just regular steps to do if we want to do AOP. The 2 snippets above mean that we want to advise the greet()
method (which resides inside Target
class) with before advice. Nothing fancy happens in the aspect, it’ll just print some information about the method invocation.
Now, this is where something is getting interesting. Let’s define a plugin inside our pom.xml.
xxxxxxxxxx
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8 </encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
The AspectJ Maven plugin stated above will weave the aspects when we execute mvn clean compile
. Now, let’s try to do just that and see what happens.
If you see inside the target directory (which consists of every compiled class) and open Target.class, you’ll see this.
xxxxxxxxxx
public class Target {
public Target() {
}
public void greet(String name) {
JoinPoint var2 = Factory.makeJP(ajc$tjp_0, this, this, name);
GdnBeforeAspect.aspectOf().beforeGreet(var2);
System.out.println("[Actual] Hi " + name + " from target!");
}
static {
ajc$preClinit();
}
}
You see that on lines 7–8, the compiler inserts additional functionality which calls the aspect we defined before. This way, the before advice will be executed before the actual process done by the target. Now you know how CTW works internally.
Post-compile (Binary) Weaving
xxxxxxxxxx
<dependency>
<groupId>com.axell</groupId>
<artifactId>aspectj-aop-lib</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
At this point, we know that greetFromLib()
exists inside our 3rd party library, which means in form of .jar file instead of our own written source codes. We need to do several modifications to our AspectJ Maven plugin to accommodate this.
xxxxxxxxxx
<plugin>
...
<configuration>
...
<weaveDependencies>
<weaveDependency>
<groupId>com.axell</groupId>
<artifactId>aspectj-aop-lib</artifactId>
</weaveDependency>
</weaveDependencies>
</configuration>
...
</plugin>
Now that we’ve added necessary information to our AspectJ maven plugin, we simply just have to execute mvn clean compile
again, and let’s see what changes inside our target directory.
xxxxxxxxxx
public class TargetLib {
public TargetLib() {
}
public void greetFromLib(final String name) {
JoinPoint var2 = Factory.makeJP(ajc$tjp_0, this, this, name);
GdnBeforeAspect.aspectOf().beforeGreetLib(var2);
System.out.println("[ACTUAL] Hi " + name + " from target lib!");
}
static {
ajc$preClinit();
}
}
Similar to what we’ve observed from CTW, the TargetLib
class (in which the source code exists on 3rd party library, we don’t host the source code in our main project) got woven by Binary Weaving by using a similar mechanism.
Load-time Weaving
- Deploy an application.
- VM initializes the weaving agent.
- The weaving agent loads all aop.xml files (Yes, we can define multiple aop.xml files and everything gets loaded).
- Weaving agent loads listed aspects in aop.xml files.
- The system starts normal execution.
- VM loads classes during execution (as usual).
- The VM notifies the weaving agent whenever it loads a class.
- The weaving agent (after being notified), inspects the to-be-loaded class to determine if any of the aspects need to be woven to the to-be-loaded class.
- If so, the weaving agent will weave the class and the aspect.
- The woven byte code will be loaded to VM and used.
Comparison Between Different Types of Weaving
Based on this research paper, these are the comparison results (compared to No-AOP implementation).
Compared to No AOP | Execution time (%) | CPU Usage (%) | Memory Usage (%) |
CTW | +3.41 | -8.5 | +3.24 |
LTW | +7.32 | -4.56 | +30.69 |
- The execution time of CTW is slightly faster than LTW. In my opinion, it’s because for CTW, the weaving process happened on compile-time, meaning that there is no operation overhead on runtime to do the weaving.
- CPU usage for CTW is also slightly lower than LTW. In my opinion, the reason is the same as the first point above.
- Memory usage for CTW is considered pretty significantly lower than LTW. In my opinion, the reason is the same as the other 2 points above.
Conclusion
I hope with this article, you guys can have a deeper overview of different types of weaving, specifically on AspectJ.
Published at DZone with permission of Axellageraldinc A. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments