In a post entitled "AOP Fundamentals", I asked for a King's English explanation of what AOP is, and what it does. I received some very helpful answers and links to articles that helped fill me in on all the theory.
But now AOP's got my full attention, and all these articles and chapter excerpts are fantastic, but in every single case they consist of lofty theory, vague UML models, and order of abstraction that are way too high-up for my liking.
Here is my understanding of AOP theory, just to clarify, so if you see something that looks wrong, let me know!:
-
Cross-cutting concerns such as Logging, Authenticating, Synchronizing, Validating, Exception Handling, etc. become highly-coupled in non-AOP systems as they are used universally by almost every component/module in the codebase.
-
AOP defines aspects (classes/methods) that abstract these cross-cutting concerns with the use of join points, advice, and pointcuts.
a. Advice – The actual code (method of an aspect, perhaps?) implementing the cross-cutting concern (i.e. doing the actual logging, validating, authenticating, etc.)
b. Join Point – An event that is triggered in non-AOP code that causes a particular aspect's advice to be executed ("woven" into the non-AOP code)
c. Pointcut – Essentially, a mapping of join points (triggering events) to advice execution
-
All aspects are modularized (LoggingAspect, AuthenticationAspect, ValidationAspect, etc.) into components and registered with an AspectWeaver. When non-AOP/POJO code comes across a join point, AspectWeaver "weaves" (integrates) the mapped advice around the non-AOP code:
public class LoggingAspect { // ... public void log(String msg) { ... } } public class ExceptionHandlingAspect { // .. public void handle(Exception exc) { ... } } public class NonAOPCode { // ... @LoggingAspect @ExceptionHandlingAspect public void foo() { // do some stuff... } } // Now in the driver public static int main void(String[] args) { NonAOPCode nonAOP = new NonAOPCode(); nonAOP.foo(); } // The AspectWeaver *magically* might weave in method calls so main now becomes: { NonAOPCode nonAOP = new NonAOPCode(); log(someMsg); nonAOP.foo(); handle(someExc); }
The $64,000 Question: Is my understanding of Java-based AOP on target, or way off, and why? How could one correctly use annotations to implement aspects, advice, join points, pointcuts and this so-called aspect weaver?
Best Answer
Let's imagine you want to log the time taken by some annoted methods using a
@LogExecTime
annotation.I first create an annotation
LogExecTime
:Then I define an aspect:
I create a class annoted with
LogExecTime
:And a main using Spring AOP:
If I run this class I'm getting the following output on stdout:
Now with the magic. As I did use Spring AOP rather than AspectJ weaver, the magic is occurring at run time using proxy-ish mechanisms. So the
.class
files are left untouched. For instance if I debug this program and put a breakpoint inoperate
you'll see how Spring has performed the magic:As Spring AOP implementation is non-intrusive and uses the Spring mechanisms you need to add the
@Component
annotation and create the object using Spring context rather than plainnew
.AspectJ on the other side will change the
.class
files. I tried this project with AspectJ and decompiled the Operator class with jad. Which lead to: