Adding AOP using Spring

I need to add some behavior to my service beans each time I start a transaction. In fact, I am converting a 2-tiers application in a web application, and previously, the users are authenticated using a real Oracle account. This way, they were able to use some user variables, using a proxy user (I will describe it in another post), now, I need to initialize these variables each time the user requests something.
As I want something transparent to the developer, I decided to add a new behavior to my service. The idea is to add a new annotation, next to the usual @Transactional to manage the variables.
Let’s go for AOP journey 🙂

First, we need to set-up the Maven dependencies, we need the standard Spring libraries and also AspectJ:

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<spring.framework.version>4.0.5.RELEASE</spring.framework.version>
	<spring.security.version>3.2.4.RELEASE</spring.security.version>
</properties>

<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.8.1</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-core</artifactId>
		<version>${spring.framework.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>${spring.framework.version}</version>
	</dependency>
	<dependency>
		<groupId>org.aspectj</groupId>
		<artifactId>aspectjtools</artifactId>
		<version>1.8.1</version>
	</dependency>
	
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-test</artifactId>
		<version>${spring.framework.version}</version>
		<scope>test</scope>
	</dependency>
</dependencies>

With AOP, I discovered some vocabulary, the most important for me are:

  • The advice: it represents the actions we want to be executed;
  • the pointcut: it’s when the advice must be executed, some of them are before, after, or around (I will use this one);
  • The aspect: it is the union of the 2 previous concepts.

Now, I have to define the class which must be called to execute whatever I want, meaning the advice:

package net.classnotfound.aop.advice;

import org.aspectj.lang.ProceedingJoinPoint;

public class AroundAdvice {

    public Object doBasicProfiling(final ProceedingJoinPoint pjp) throws Throwable {
        // start stopwatch
        System.out.println("Start advice...");
        Object retVal = pjp.proceed();
        // stop stopwatch
        System.out.println("Finished advice!");
        return retVal;
    }
}

This class needs to define a method with org.aspectj.lang.ProceedingJoinPoint in its method signature. This is mandatory to be able to execute my annotated method.

The annotation is only used as a marker:

package net.classnotfound.aop.annotation;

public @interface Advisable {
    //Nothing to do!
}

The service defines a method which is annotated with my tag:

package net.classnotfound.aop.service;

import net.classnotfound.aop.annotation.Advisable;


public class MyServiceImpl implements MyService {

    @Advisable
    public void doSomething() {
        System.out.println("Does something very important!");
    }

    public void doSomethingElse() {
        System.out.println("Does something else more important!");

    }
}

And the trick is done using the Spring configuration file (I prefer using it instead of the annotation config), in which we put all together and tell Spring when the advice must be called:


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="myService" class="net.classnotfound.aop.service.MyServiceImpl" />

    <bean id="aroundAspect" class="net.classnotfound.aop.advice.AroundAdvice" />
    <aop:config>
        <aop:aspect ref="aroundAspect">
            <aop:pointcut id="aroundPointCut"
                expression="execution(* net.classnotfound.aop.service.*.*(..)) && @annotation(net.classnotfound.aop.annotation.Advisable)" />
            <aop:around pointcut-ref="aroundPointCut" method="doBasicProfiling" />
        </aop:aspect>
    </aop:config>
</beans>

We can see the pointcut and the aspect definitions.

And now, each time a method which is in defined in a class from the net.classnotfound.aop.service package and annotated with my Advisable tag, the advice is called before (and after) calling the real method.

Note: to order the execution of different advices, we have to use the order attribute on the aspect element.

Now, I will have to add the real implementation of my business, but it is not in the scope of this blog 😀

Source files are available here.

Tips: Some time, we need to define an execution order, in my case, it is important that my advice is triggered after the transaction started, to do that, nothing more complicated than adding an order attribute:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <tx:annotation-driven order="50"/>
[...]
    <aop:config>
        <aop:aspect ref="aroundAspect" order="100">
[...]
        </aop:aspect>
    </aop:config>
</beans>

By adding this attribute, we tell the AOP engine to process the transactional annotation before mine.

Leave a comment