1. Introduction
In this tutorial, we’ll introduce AOP (Aspect Oriented Programming) with Spring and start understanding how we can start using this powerful tool in practical scenarios.
It’s also possible to leverage AspectJ’s annotations when developing using Spring AOP but in this article, we’re focusing on the core Spring AOP XML-based configuration.
2. Overview
AOP is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. It does so by adding additional behavior to existing code without modification of the code itself.
Instead, we can declare this new code and these new behaviors separately.
Spring’s AOP framework helps us implement these cross-cutting concerns.
3. Maven Dependencies
Let’s start by adding Spring’s AOP library dependency in the pom.xml:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.7.RELEASE<version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> </dependencies>
The latest version of the dependency can be checked here.
4. AOP Concepts and Terminology
Let’s briefly go over the concepts and terminology specific to AOP.
4.1. Business Object
A business object is a normal class which has a normal business logic. Let’s look at simple example of a business object where we just add two numbers:
public class SampleAdder { public int add(int a, int b) { return a + b; } }
Note that this class is a normal class with business logic and without any Spring-related annotations.
4.2. Aspect
An aspect is a modularization of a concern that cuts across multiple classes. Unified logging can be an example of such cross-cutting concern.
Let’s see how we define a simple Aspect:
public class AdderAfterReturnAspect { private Logger logger = LoggerFactory.getLogger(this.getClass()); public void afterReturn(Object returnValue) throws Throwable { logger.info("value return was {}", returnValue); } }
In the above example, we’ve just defined a simple Java class which has a method called afterReturn that takes one argument of type Object and it just logs in that value. Note that even our AdderAfterReturnAspect is a standard class, free of any Spring annotations.
In the next sections, we’ll see how we can wire this Aspect to our Business Object.
4.3. Joinpoint
A Joinpoint is a point during the execution of a program, such as execution of a method or the handling of an exception.
In Spring AOP, a JoinPoint always represents a method execution.
4.4. Pointcut
A Pointcut is a predicate that helps match an Advice to be applied by an Aspect at a particular JoinPoint.
The Advice is often associated with a Pointcut expression and runs at any Joinpoint matched by the Pointcut.
4.5. Advice
An advice is an action taken by an aspect at a particular Joinpoint. Different types of advice include “around,” “before” and “after” advice.
In Spring, an Advice is modeled as an interceptor, maintaining a chain of interceptors around the Joinpoint.
4.6. Wiring Business Object and Aspect
Let’s look at how we can wire a Business object to an Aspect with an After-Returning advice.
Below is the config excerpt that we’d place in a standard Spring config in the “<beans>” tag:
<bean id="sampleAdder" class="org.baeldung.logger.SampleAdder" /> <bean id="doAfterReturningAspect" class="org.baeldung.logger.AdderAfterReturnAspect" /> <aop:config> <aop:aspect id="aspects" ref="doAfterReturningAspect"> <aop:pointcut id="pointCutAfterReturning" expression= "execution(* org.baeldung.logger.SampleAdder+.*(..))"/> <aop:after-returning method="afterReturn" returning="returnValue" pointcut-ref="pointCutAfterReturning"/> </aop:aspect> </aop:config>
As can be seen, we’ve defined a simple bean called simpleAdder which represents an instance of a Business Object. In addition, we’re creating an instance of an Aspect called AdderAfterReturnAspect.
XML is, of course, not our only option here; as mentioned before, AspectJ annotations are fully supported as well.
4.7. Configuration at Glance
Tag aop:config is used for defining AOP-related configuration. Within the config tag, we define the class that represents an aspect. We’ve given it a reference of “doAfterReturningAspect” aspect bean that we created.
Next, we define a Pointcut using the pointcut tag. Pointcut used in example above is execution(* org.baeldung.logger.SampleAdder+.*(..)) which means apply an advice on any method within SampleAdder class that accepts any number of arguments and returns any value type.
Next, we define which advice we want to apply. In the above example, we’re going to apply after-returning advice which is defined in our Aspect AdderAfterReturnAspect by executing method named afterReturn defined using attribute method.
This advice within Aspect takes one parameter of type Object. The parameter gives us an opportunity to take an action before and/or after the target method call. In this case, we just log the method’s return value.
Spring AOP supports multiple advices using annotation-based config – this and more examples can be found here and here.
5. Conclusion
In this tutorial, we illustrated concepts used in AOP and example of using the AOP module of Spring. If you’re interested in discovering more about AOP, here’re some resources:
- An introduction to AspectJ
- Implementing a Custom Spring AOP Annotation
- An introduction to Pointcut Expressions in Spring
- Comparing Spring AOP and AspectJ
- An introduction to Advice Types in Spring
The implementation of these examples can be found in the GitHub project – this is a Maven-based project, so it should be easy to import and run as is.