In this article we will look at Spring AOP which is one of the two core concepts of Spring with the other being DI(Dependency Injection) and IoC (Inversion of Control).
So what is AOP ? Lets get the definition out of the way first .
AOP extends the traditional Object Oriented Programming (OOP) model to improve code reuse across different object hierarchies. The basic concept in AOP is an aspect, which is a common behavior that’s typically scattered across methods or classes.
Hang on we will go through the examples which will clear things up a bit.
What does this Aspect contain and how does it improve code reuse?
An aspect contains cross-cutting concerns which is generally not associated with business logic and usually is scattered across our entire application when we do not use AOP. A Project can have any number of aspects associated.
So what are these cross-cutting concerns ?
Transaction Management , Security and Logging are some of the common use cases of AOP and there are a few others as well. But to keep it simple we will focus on these concepts.
Here is functional explanation of how our project might look with and without AOP.
So if you have not worked with AOP before you might be wondering , why isn’t this used more commonly.
We have been using AOP all along in any application using a Spring based framework it is just that in most cases it is abstracted from us. Below code block shows a typical Hibernate Session Management and persistence.
So now we will let Spring manage our Transaction while we focus on saving the User object alone. We need to annotate our DAO method with @Transactional . Although in production we should always use @Transactional in our service class which calls the DAO as both have the same effect.
So How does Spring manage to automatically begin the transaction and commit the transaction once we save our object ? Yeah you guessed it AOP !!!
Enough with the theory now let’s get our hands dirty and write some code. We will do a pretty basic project where we create our own Aspect which will run automatically based on various conditions .
- Create a Simple Maven Project with the following dependencies
2. The project structure should look like the one below . We will go through what each class does and explore the Aspect class in detail.
3. Below is our main class which gets user details through our service class.
4. Our service class and DAO class simply returns the user details . We don’t use database here as we keep it simple and simulate a database call.
5. In Spring Configuration file we need to explicitly enable support for AspectJ through @EnableAspectJAutoProxy annotation
6. In any of our above code we have not done any logging . All our logging will be done in our Aspect class. We have two Aspects ApplicationAspect and UserAspect. We will explore Application Aspect first
First we declare our class as an Aspect using @Aspect. An aspect is simply a class to write our cross-cutting concerns. In above example our intention is that we need to log a statement before every DAO method call doesn’t matter where the call is coming from.
@Order(1) indicates if more than one Aspect is supposed to run before a given method this Aspect will have the highest priority.
Advice is the actual action to be taken either before or after the method execution. This is an actual piece of code that is invoked during the program execution.Here executeDAOAdvice() is the advice which will be executed Before our target method .
Pointcut – This is an expression language which determines at what point in our application the particular advice should run . In above example our intention is that we need to log a statement before every DAO method call. So in our expression we do the below :
This indicates that we need our advice to run for any method (*) inside the dao package having any name (*) , any return type(*) and any number of arguments (..)
Bear with me if you dont get it initially , Pointcut expression language is a whole topic in itself.
So far we have configured on which methods our advice needs to be called but the below statement is required to make sure it runs Before the target method.
We will see another example with the UserAspect which might show another way to utilize Aspects.
Our intention with UserAspect is that whenever user details get returned from any method we want to intercept it and do some modification before it reaches the destination . Do remember that in earlier case we wanted to log only before a dao method call.
@Order(2) here indicates that our ApplicationAspect will run first and only then UserAspect will run in case both are called on the same method. But here in this example our ApplicationAspect is called only for methods in dao package whereas UserAspect is only for Service package.
Our above pointcut expression indicates that we need our advice to execute for any return type (*) and for any class in the org.aop.main.service package (*) and for any method name that starts with getUserAccount*(..) with any number for arguments.
So next up we want it to run after a method returns so that we can get the result of that method.
Previously we used @Before and now we have to use @AfterReturning and we have access to the result returned here as well as arguments passed to the method.
Types of Advice :
Before advice: Advice that executes before a join point, but which does not have the ability to prevent execution flow proceeding to the join point (unless it throws an exception).
After returning advice: Advice to be executed after a join point completes normally: for example, if a method returns without throwing an exception.
After throwing advice: Advice to be executed if a method exits by throwing an exception.
After (finally) advice: Advice to be executed regardless of the means by which a join point exits (normal or exceptional return).
Around advice: Advice that surrounds a join point such as a method invocation. This is the most powerful kind of advice. Around advice can perform custom behavior before and after the method invocation. It is also responsible for choosing whether to proceed to the join point or to shortcut the advised method execution by returning its own return value or throwing an exception.
So our output will look like the below one :
Now going back to our @Transactional annotation it internally uses @Around Advice so that it can open a session for transaction as well as close the session after our commit.
Spring AOP vs AspectJ
AspectJ is the original founder of Aspect Oriented Programming . Spring AOP is a lightweight implementation of AspectJ and utilizes many of its features.
Weaving is the technique in which our aspect code is wired into our application. Spring AOP uses run-time weaving whereas AspectJ has compile-time, load-time, run-time weaving to name a few.
Run-time weaving will slightly affect the performance of our application but it is only by a few nano-seconds.
AOP is a powerful concept and even if we may not be using it directly it will help us understand any Spring based framework better . This is a simple introduction to AOP and one needs to explore more and get their hands dirty to benefit more .
Github Repository for the sample Project :
DZone – Java
Chad Darby – Author luv2code.com