Aspect Oriented Programming with Java and SpringBoot

This blog covers the basics of Aspect Oriented Programming (AOP). I’ll show a simple working example of AOP: a common task like logging of REST calls can be generically defined in an Advice, which can then be applied to various target places in our code (so called Pointcuts) via an Aspect.

For the impatient: you can find the end result on my Github repo:

Programming Paradigms

Back in the 1996, when Java 1.0 was released, Java developers were all hyped up about object oriented programming, also called OOP. While OOP was one of the foundational drivers for Java, the programming language itself has gone a long way since then and now supports many programming paradigms.

Here’s a list of the primary programming paradigms supported in Java (in historical order):

  • Procedural programming
  • Object oriented programming (OOP)
  • Functional programming
  • Aspect oriented programming (AOP)

For this post, we focus on AOP and show how to create Aspects. You’ll learn both the basics of AOP as well as how to use it with SpringBoot.

Why AOP?

Most bigger companies have programming guidelines, and so does mine. One of our guidelines states that every REST endpoint execution must be logged (name of the Java method + the parameters).

Here’s how you could solve this:

The code snippet above does the following:

  • @RestController: Make sure SpringBoot knows this class contains REST endpoints
  • @GetMapping: A method which replies to HTTP GET requests
  • System.out.println(...): adhere to the aforementioned coding guidelines
  • return value: the method simply returns a greeting message of type String

In a realistic app, you will have many such REST calls, in many different classes. Doing the exact same logging in all those methods is cumbersome. Moreover, if the coding guidelines slightly change, you will have to change the logging message in each method.

Here’s where AOP comes to the rescue: with the help of AOP, we can nicely add common functionality to many different places in our code, without interfering with existing code. In literature jargon, AOP is all about the separation of cross-cutting concerns.🤓 In more human understandable language, AOP enables the modularization of common tasks across different objects.😎

Maven Dependency

To start using AOP in SpringBoot with AspectJ annotations, we need to import the following dependencies in our pom.xml:

Advice

Let’s create a function which performs our required logging in a generic way:

This generic function is called an Advice. Note that it can log the name and parameters of any method; let’s break the Advice down step by step:

  • JoinPoint: this object contains all information about the Join point, that is, the "location" where our Aspect will be inserted. In our case, this would be the REST method for which we want to create a log message for.
  • joinPoint.getSignature() and joinPoint.getArgs() extracts the method signature as well as the calling arguments
  • System.out.println(...): do the necessary logging

Pointcut

So where do we want to insert the above Advise method? Well, we want each REST endpoint to be tracked. While there are many ways to mark our REST endpoints, we choose to use a custom annotation to define the Pointcut:

As you can see, the Pointcut definition is just a one-liner:

  • @Before: we run the Advice before the REST call gets answered
  • @annotation: we mark Pointcuts via an annotation
  • LogMethod: this is the name of our custom annotation

Now we’re ready to mark our REST method with our custom annotation:

Note that we prepended the REST method with the annotation @LogMethod. Moreover, we removed the logging inside the method, this is now done by our Aspect.

Aspect

An Aspect is a Pointcut plus an Advice. So, let’s put the two together, and we get:

Here’s what we have:

  • @Aspect: SpringBoot expects all Aspects to be in classes annotated with @Aspect
  • @Before(...): the Pointcut
  • logMethodName(...){...}: the Advice

So all we did here was just bring together the previously shown Pointcut expression plus the Advice, and wrap everything in a class. Bring out the champagne, we have our Aspect all finished and working 🥂

Enable AOP

To wrap up, we have to enable AspectJ for our Spring configuration:

Remember that we want to be able to work with Beans when using Spring. At the moment, our @RestController class only contains the REST-call logic, but not our Advice. Spring can create Proxies for such Beans which contain this additional logic (the Advice), and this is enabled by @EnableAspectJAutoProxy.

Conclusion

That’s all! You now have a fully working example of AOP😀💪🍾

We implemented an Advice to be run anytime a method with annotation @LogMethod is executed. Thanks to our AOP approach, we can add this annotation to future REST methods which will then be advised with the same Aspect!

Checkout the fully working example on Github:

This Github repo also contains a second advice of type @Around: Each time a REST method is called, we log the execution time. This can come in handy to measure, monitor and compare the performance of different REST endpoints.

Thanks for reading, please leave a comment if you have any feedback or questions!😀

Further readings

For the curious, here’s some more reading material:

AOP primer and Advice types:
In our example, we used an Advice of type @Before. Alternatively, you can use @After, @Around or @AfterThrowing.

Pointcuts are predicates that match a set of Join points. We used annotation-driven Pointcuts, but Spring supports many more designator types. For example, Spring supports execution Pointcuts where a method name has to match a given pattern.

AOP Proxies: an explanation in the official Spring documentation.

Originally published on Dev.to.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Philipp Gysel

I love finance and computer science. I’m interested in long-term investing and Java/SpringBoot applications.