I'm an Agile and Lean Strategist specialised in coaching and managing the transformation of IT departments, from startups to enterprise-scale organisations, to highly efficient, productive and energised environments. I also have experience as senior development manager and architecture governance in large enterprises, especially in the finance sector. Marco is a DZone MVB and is not an employee of DZone and has posted 26 posts at DZone. You can read more from them at their website. View Full User Profile

AOP made easy with AspectJ and Spring

05.16.2011
| 16026 views |
  • submit to reddit

I recently started looking at Aspect Oriented Programming (AOP) and I'm finding it exciting to say the least. Of course I was acquainted with it, since I saw it used for transaction management within Spring but I have never looked at it in depth. In this article I want to show how quick it is to get up to speed with AOP and Spring thanks to AspectJ. The material in this article is based on the excellent AOP book AspectJ in Action by Ramnivas Laddad. 

AOP is not a language, but rather an approach to software engineering. Like any methodology it has got different implementations and  AspectJ is currently the richest and most complete of all. Since AspectJ and AspectWerkz merged, it is now possible to create aspects using annotations.

The reason developers write code is to provide functionality of some sort. The kind of functioniality is not important for this discussion: some might want to deliver business functionality, others might write code for research purposes, other for sheer fun. The point is that any information system has got a core motive, a key functionality which it wants to deliver. For instance, I recently wrote PODAM, a testing tool which has as its ultimate goal that of automatically fill POJO / JavaBean properties.

Every information system has also got needs for orthogonal services (what AOP calls crosscutting concerns); for instance logging, security, auditing, exception management and so on. While an information system can be divided into discrete pieces of functionality (what AOP defines join points), orthogonal services are required across the board. For instance, if one wanted to log how long the execution of every single public method took, each public method should have something like the following pseudo-code:

public void someBusinessMethod() {

long start = System.currentTimeInMilliseconds();

doTheBusinessFunctionality();

long end = System.currentTimeInMilliseconds();

log.debug("The execution of someBusinessMethod took " + (end - start) + " milliseconds");

}

 

In the above method, the core functionality is identified solely by someBusinessMethod() whereas everything else is just logging activity. It would be nice to have something like :

//Some external magic happens before the invocation of this method to take the start time

public void someBusinessMethod() {

doTheBusinessFunctionality();

}

//Some external magic happens after the invocation of this method to take the end time and logs how long the execution took.

Developers typically want logging, security, etc. throughout their application, not for a single method; AOP allows developers to achieve this goal by defining somewhere externally (called an Aspect) the behaviour to apply to all code matching some pattern (AOP actually allows for a broader set of functionalities, such as the possibility to add interfaces, instance variables, methods, etc to a class just to name one). This empowered behaviour is then somewhat added to the final executing code by what AOP calls a Weaver.

There are various ways that this can be achieved: weaving can happen at the source level, at the binary level and at load time. You could think of the weaver as the linker in C and C++; sources and libraries are linked together to create an executable; the weaver combines together Java code and aspects to create empowered behaviour.

Spring achieves this empowered behaviour by creating an AOP proxy around the code whose behaviour must be enriched. The code that follows shows a very simple example based on AspectJ; the example surrounds the execution of a simple method with some Authentication service.

The Authentication services looks very simple (the point is not how the functionality has been implemented but rather that an authentication service is available) :

/**
*
*/
package uk.co.jemos.aop;

/**
* A simple authenticator service.
*
* @author mtedone
*
*/
public class Authenticator {

public void authenticate() {
System.out.println("Authenticated");
}

}

 

Now let's have a look at the business logic:

/**
*
*/
package uk.co.jemos.aop;

/**
* A simple service which delivers messages
* @author mtedone
*
*/
public class MessageCommunicator {

public void deliver(String message) {
System.out.println(message);
}

public void deliver(String person, String message) {
System.out.println(person + ", " + message);
}

}

 

What we would like is for the Authenticator to be invoked before the invocation of any of the business methods of MessageCommunicator. Using AspectJ annotation syntax, we write in Aspect  in pure Java:

package uk.co.jemos.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class SecurityAspect {

private Authenticator authenticator = new Authenticator();

@Pointcut("execution(* uk.co.jemos.aop.MessageCommunicator.deliver(..))")
public void secureAccess() {
};

@Before("secureAccess()")
public void secure() {

System.out.println("Checking and authenticating user...");
authenticator.authenticate();

}

}

 

The code above is a bit more interesting. An Aspect is marked with the @Aspect annotation. A Pointcut is some point of interest in our code, where we would like our Aspect to kick in. The syntax @Pointcut("execution(* uk.co.jemos.aop.MessageCommunicator.deliver(..))")

public void secureAccess() {
};

 

means: "Define a Pointcut named secureAccess which applies to all deliver methods within the MessageCommunicator class, regardless of the return type of such method".

What follows is called an advice, and it's where AOP empowers the behaviour of our class:

@Before("secureAccess()")
public void secure() {

System.out.println("Checking and authenticating user...");
authenticator.authenticate();

}

 

The code above says: "Before any match of the secureAccess() Pointcut apply the code within the block". All of the above is pure Java, although the annotations belong to the AspectJ runtime.

To use the above aspect with Spring, I defined a Spring context file:

<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

<aop:aspectj-autoproxy />

<bean id="messageCommunicator" />

<bean id="securityAspect" />

</beans>

 

The XML element:  <aop:aspectj-autoproxy /> instructs Spring to create a proxy around every aspect.

Now when I use the MessageCommunicator from a client:

/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"classpath:aop-appContext.xml");

MessageCommunicator communicator = ctx.getBean("messageCommunicator",
MessageCommunicator.class);
communicator.deliver("Hello World");
communicator.deliver("Marco", "Hello World");

}

 

I get the following output:

INFO: Loading XML bean definitions from class path resource [aop-appContext.xml]
15-May-2011 11:51:41 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@21b64e6a: defining beans [org.springframework.aop.config.internalAutoProxyCreator,messageCommunicator,securityAspect]; root of factory hierarchy
Checking and authenticating user...
Authenticated
Hello World
Checking and authenticating user...
Authenticated
Marco, Hello World

 

AOP substantially changes the way we think software engineering, by allowing us to externalise crosscutting concerns in external components which are then weaved into our code when needed.This allows for cleaner and more maintainable code and the implementations are limitless. Additionally, if we are careful in writing our Aspects by making them reusable, we can quickly come up with a library of general-purpose, reusable aspects which add functionality to our code in an injected way.

There are obviously drawbacks in the adoption of AOP, mainly the learning curve which is required by developers to get acquainted with the technology. AspectJ defines its own language and syntax, as the example above demonstrates); the @Before annotation is just one possibility: advices can be applied before, after, around objects; additionally the syntax to define Pointcuts is not Java but rather script-like. AspectJ aspects also have keywords and native objects to capture the context of the join points they advice, and this syntax needs to be learned. However, the potential gains outweight by large the extra effort required in learning this new and exciting technology.

Happy Technology!

 

From http://tedone.typepad.com/blog/2011/05/using-aop-easily-with-aspectj-and-spring.html

Published at DZone with permission of Marco Tedone, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Jerome Raduget replied on Fri, 2011/05/20 - 6:41am

It may be a bit easiest to start aspectj with spring (no need of compile time weaving or of a java agent for load time weaving). But using aspect with spring (aop:aspectj-autoproxy) really reduces the panel of fonctionnalities and the powerfull features of your aspect (http://static.springsource.org/spring/docs/3.0.x/reference/aop.html). And this could avoid a headache for the developper to make works its aspect with spring (especially when he don't really know how spring (proxy) and aspectj (weaving) works internally.)

Personnally, I preferer a direct use of aspectJ without spring (maven or eclipse integration is really good ). And I agree with you to say that aspectJ is really a great and very powerfull tool !

Marco Tedone replied on Sun, 2011/06/05 - 3:32am in response to: Jerome Raduget

Hi Jerome, I totally share your view. In fact I also think that one should use AspectJ directly to have the full spectrum of AOP capabilities.

 

Kotrappa Sirbi replied on Thu, 2011/06/23 - 12:22pm

Hello I agree with you AOP is powerful but where are all those benefits still they are in research and if any large Industry AOP projects are there let me know.I know it needs time for developers and stackholder must accept this technology.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.