John Melton's Weblog
Java, Security and Technology

A Simple Spring AOP Tutorial

Print this article

No Gravatar

The Spring framework supports AOP very elegantly. Though it does not offer some of the features that AspectJ offers, it also is typically a simpler configuration to get going. This post is just an example of doing a very simple task (logging), a “cross-cutting concern” in AOP lingo, using the Spring framework.

This example will exist of a class with a main method, a business logic interface / class combo, an Advice (Spring’s way of encoding the AOP logic), and the associated Spring configuration file that ties everything together.

This example does not go into great detail about how Spring’s AOP mechanism works, but there is plenty of information in the Spring documentation about that. It simply uses the Java proxy mechanism. Also, I don’t go into all of the options for how you can configure AOP in Spring, though there are several. I only focus on the most recent recommendations.

Having said all of that … here we go.

First for the business logic interface / class:


package com.jtm.aop;

public interface SomeIntf {

	public void updateMe1();
}


package com.jtm.aop;

import org.apache.log4j.Logger;

public class MyClass1 implements SomeIntf {
	Logger log = Logger.getLogger(this.getClass());

	public void updateMe1() {
		log.info("in updateMe1");
	}
}

This was obviously a very simple class that just writes a log statement. Now onto the Advice mechanism:


package com.jtm.aop;

import java.lang.reflect.Method;

import org.apache.log4j.Logger;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

public class PerformanceLoggingAdvice implements
	MethodBeforeAdvice,
	AfterReturningAdvice {

	/** Time in milliseconds */
	long startTime = 0;

	/** Time in milliseconds */
	long finishTime = 0;

	protected static final Logger log =
		Logger.getLogger(PerformanceLoggingAdvice.class);

	public void before(Method method, Object[] args,
			Object target) throws Throwable {
		startTime = System.currentTimeMillis();
		log.debug("Executing method " + method.getName()
			+ " on object " + target.getClass().getName());
	}

	public void afterReturning(Object returnValue,
			Method method, Object[] args, Object target) throws Throwable {
		finishTime = System.currentTimeMillis();
		double totalDuration = finishTime - startTime;
		log.debug("Finished executing method " + method.getName()
			+ " on object " + target.getClass().getName() + " in "
			+ totalDuration / 1000 + " seconds.");
	}

}

This class is doing a bit more. This class implements the Spring framework’s before and after advice interfaces. This allows the Spring framework to call these methods before and after the methods in the application where they are configured to do so by the Spring config file.

Now let’s see the main driver class:


package com.jtm.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class RunAll {
	public static void main(String[] args) {
		SomeIntf myClass1;

		ApplicationContext appContext =
			new ClassPathXmlApplicationContext(new String[] {"spring-config.xml"});

		myClass1 = (SomeIntf) appContext.getBean("myClass1");

		myClass1.updateMe1();
	}

}

As you can see, this class simply loads Spring, locates the bean, and calls the update method.

Now on to the magic, the Spring config 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-2.5.xsd


http://www.springframework.org/schema/aop


http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

	">

	<bean id="myClass1" class="com.jtm.aop.MyClass1" />

	<bean id="performanceLoggingAdvice"
		class="com.jtm.aop.PerformanceLoggingAdvice" />


	<aop:config>
		<!-- Performance logging pointcut -
			run for every method in a control or facade class -->
		<aop:pointcut id="performanceLoggingPointcut"
			expression="execution(* com.jtm..*.update*(..))" />

       		<aop:advisor
           		advice-ref="performanceLoggingAdvice"
            		pointcut-ref="performanceLoggingPointcut"
            		id="performanceLoggingInterceptorAdvisor"  />

	</aop:config>
</beans>

As you can see, there is more going on here than in the other sections. Let’s break this down.

1. The business logic and Advice classes are configured as standard beans
2. The aop namespace for Spring 2.5 is loaded at the top of the file
3. All of the AOP configuration is located within an aop:config tag
4. First we configure the pointcut, which is a regular-expression like description of when the performance logging code should be run. In this case, we have configured it to run on any class in any subpackage of the com.jtm package and on any method that starts with “update” and that takes any kind of parameters.
5. Next we configure the advisor, which combines the advice class with the pointcut.
6. Finally Spring looks at the code are runtime and auto-proxies the classes that need to be so that the AOP code can be applied at run-time.

That’s it! This is a quick run-through. If you have any further questions, feel free to post here or search for more tutorials online. Also, check out the Spring documentation for further information.

Hope this helps.
-jtm

Be Sociable, Share!

Comments

  • abu

    this is pretty useful.