In this post I will show you how to use Spring aspects. In contrast to AspectJ aspects that are implemented by either compile time or load time bytecode manipulation (process often called waving), Spring aspects are implemented using proxy classes. The main advantage of proxy aspect implementation is ease of use, the main disadvantage is reduced functionality of aspects (e.g. we cannot intercept calls to static methods).
Diagram below illustrates how proxy classes are used to
add functionality contained in
Aspect I and
Aspect II to
When application asks Spring for
implementation Spring detects that there are aspects attached to
so instead of returning
Spring creates and returns a proxy.
Proxy returned to client implements
and by default redirects all method calls to
In some situations like e.g. calling a
proxy may execute code (called advice) from
Aspect I and/or
thus adding functionality to
Before we create our first aspect we need to setup our application.
Let’s start with Maven dependencies. We will need
You may be wondering why we need something from AspectJ which we
don’t use. Spring Framework supports not only proxy based aspects
but also full blown AspectJ aspects, to avoid code duplication
designers of Spring decided to borrow annotation definitions like
from AspectJ project.
aspectjweaver is only used as an annotation library and nothing more.
Next we need to create Spring configuration class and bootstrap Spring context:
NOTE: To enable proxy based aspects we need to add
annotation to our configuration class.
Before we start let’s introduce some terminology. Advice is
a piece of code that should be executed when certain event
like calling a method takes place. A pointcut is a set of
events, for example all calls to a method
foo() contained in
Bar. A join point is a single event for example a
particular invocation of method
on line 105 in class
Aspect is a pointcut-advice pair, in other words aspect defines
what should be done (advice) and when (pointcut).
Spring borrowed this terminology from AspectJ, it takes a while
to get used to it.
We will start by crating
@After aspects that
as their names suggest are invoked before and after a method call.
Our aspects will add functionality to the following component:
Let’s start with
(here I use the same name for aspect and advice, but remember that they
are two different things):
A few things to notice:
DummyAspectclass will contain definitions of our aspects, we may define many aspects inside a single class
DummyAspectmust be registered as a Spring component (here I used
@Componentannotation). This also means that dependency injection works inside aspects
- Class must be marked with
@Aspectannotation otherwise Spring will ignore our aspects
- Optionally we may provide
@Orderannotation that specifies order of aspects (e.g. when there is more than one aspect attached to a given method call). The higher the order value the more close the aspect is to the original method call, see the diagram below:
Now let’s see how
@Before aspects works.
A pointcut defines a set of events (like calling a method) to which we want to
For example to create a pointcut that will “point” to every invocation of
DummyComponent::doStuff method, we may write:
This code creates named pointcut with
Strange expressions passed to
@Pointcut annotation is
borrowed from AspectJ, it tells Spring that we want to
select method calls
execution, of methods that may return any
*, and are members of
and are named
doStuff, and doesn’t take any parameters
Now let’s move to the advice:
Advice is implemented as an instance method, first we
declare that this is a
@Before advice - so it will be called
before target method. We also define where we want to use
advice by passing pointcut name to
Advice method may optionally have a
JoinPoint argument that
represents particular invocation of
JoinPoint contains many useful informations
doStuff() method arguments, or value of
Let’s check if our aspect works:
Yay! It is but since
doStuff doesn’t have any parameters we
can’t test arguments logging. We will fix that now, by adding
a single parameter of type
Since we changed method signature we must also change our pointcut definition:
We are using
.. to tell Spring that method may have any number of arguments.
We may also specify exact number and types of arguments for example:
With changed pointcut we now get:
Sometimes we want to extract method argument value, instead
of manually extracting argument from
JoinPoint we may ask Spring
to do this for us.
Let’s add another parameter to
Then let’s define another aspect:
Here we use
args expression to bound method arguments to
variables. Then we may use
arg2 as a parameters in aspect method.
Don’t forget to add parameters to pointcut name in
@Before annotation otherwise
you will get nasty exception with strange and unhelpful message.
Modifying method parameters
Aspects allow us to easily change values of method arguments. For example given method:
We may create aspect
toUpperCase that will uppercase user name
before passing argument to target method.
@Before aspect is not powerful enough to do this,
we will need
@Around advice has a single parameter of type
represents pending target method invocation. This is very powerful feature since
it allows us to change method parameters and return value, wrap
thrown exceptions or even skip method call altogether.
Here we simply invoke target method with changed arguments using
Modifying return value
Aspects allow us to change return value of a method.
For example let’s add method to our
Notice that for
size equal zero
Returning null instead of empty collection
isn’t good programming practice let’s change that
behaviour using aspects.
We will start with already familiar
@Around advice method returns value then that
value will be used as return value
of the target method, this is exactly what we do here.
If we only want to access return value we may also use
Here we cannot change returned value itself but we may call methods on it, set properties etc.
We may use
@Around advice to intercept, handle or wrap exceptions thrown
by target method (just add ordinary
try..catch statement around
proceed call). Here we will concentrate on
that allows us to inspect exceptions thrown by target method.
DummyComponent we must add method:
We must also declare our exception class:
And pointcut-advice pair:
Aspects and interface methods
So far we only attached advices to concrete classes like
in real applications we often want to attach advices to all implementations
of given interface.
Fortunately for us Spring supports this scenario.
We will start by declaring
and its two implementations:
Now we may attach our advice to
In pointcut expression I used
DummyInterface+ to select
all classes that implement
In pointcut expression we are not limited to a single method, we may use
DummyInterface+.*(..) expression to attach advice to all interface methods.
Let’s check if our advice works:
Aspects and annotations
Another common scenario in real life apps is to attach advices to methods marked with given annotation. Let’s start by creating custom annotation:
Then we must create test method in
DummyComponent and mark it with
And finally we must create pointcut-advice pair:
In pointcut expression we use
* *.*(..) to signify that we want
to consider methods with any return type, within any class, with any
name and taking any number and types of arguments.
But we also use
to point only to these methods that are annotated with
Often in advice we want to access annotation to read some values from it.
To access annotation we may modify our
@Before advice to:
Aspects and proxy unwrapping
Since Spring aspects are implemented using proxy classes we may skip advice invocation by unwrapping Spring bean:
We only scratched the surface of what Spring aspects can do, and we only used basic expressions in pointcut definitions. Aspect oriented programming is a huge topic and requires time and practice to master. I hope that this blog post helped you to understand what apects are and how to use them in Spring. If you have any remarks how I can improve this post please leave a comment.