Tech Brainwave

A Road Map for Innovative Technologies

Spring 3.0 AOP Advice

Posted by giftsam Posted on Dec - 01 - 2010

Introduction
Abbrevation of Spring AOP is Aspect-oriented programming, Action taken by an aspect at a particular join point is known as Spring AOP advice. To say simple, Spring models an advise as an interceptor and maintains a chain of interceptors by adding functionalities before or after the method execution. In this article, the various types of AOP advice in Spring 3.0 is explained in an elegant way. The types are,

  1. Before Advice
  2. After Returning Advice
  3. After Throwing Advice
  4. Around Advice

Required Jars

  • Latest Spring jars(Download, Extract and add the jar files in the library folder)
  • aopalliance.jar
  • commons-logging.jar

Optimal explaination by samples
For easy understanding, In this article the spring AOP advice is explained by samples. The sample contains only one Spring context configuration file named “adviceContext.xml”, In which an interface named “Sample” and its implementation class “SampleImpl” together with a aspect configuration bean named “AspectConfigBean” is defined. Since the configuration file and the interface is same for all the types of AOP, this is given below,

Listing 1 – adviceContext.xml



<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
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

">
<!-- Enable the @AspectJ support -->
<aop:aspectj-autoproxy />
<bean id="aspectConfigBean class="com.sample.aop.config.AspectConfigBean"/>
<bean id="sampleBean" class="com.sample.aop.advice.SampleImpl"/>
</beans>


<aop:aspectj-autoproxy /> – is used to enable the @AspectJ support.

Listing2 – Sample.java



package com.sample.aop.advice;

/**
* @author giftsam
*/
public interface Sample
{
void printValue();

}

Aspect Annotation
In Spring 3.0, Aspects are implemented by two ways, First way is by using schema based approach in regular classes and the other way is to annotate the regular classes with the "@Aspect” annotation (@AspectJ style). In the article’s sample application the @Aspect annotation is defined in the class “AspectConfigBean”(Listing 3, 6, 9, 12) to configure the spring AOP.

Pointcut Annotation
The pointcut expression is indicated using the annotation “@Pointcut”. It enable us to control when the advice executes. In the sample application the pointcut expression is defined in the class “AspectConfigBean”(Listing 3, 6, 9, 12) as “@Pointcut(“execution(* com.sample.aop.advice.*.*(..))”)  annotation to access all the public method inside the “com.sample.aop.advice” package.

Step1 – Before Advice
The annotation @Before is used to declare the before advice and it executes before the implementation class “SampleImpl”(Listing 4) method “printValue”.

Listing 3 – AspectConfigBean.java


package com.sample.aop.config;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
* @author giftsam
*/
@Aspect
public class AspectConfigBean
{
@Pointcut("execution(* com.sample.aop.advice.*.*(..))")
public void adviceMethods()
{
}

@Before("adviceMethods()")
public void execute() throws Throwable
{
System.out.println("Before Method started excuting...");
}
}

Listing 4 – SampleImpl.java


package com.sample.aop.advice;

/**
* @author giftsam
*/
public class SampleImpl implements Sample
{
public void printValue()
{
System.out.println("Started Printing.. ");
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
System.out.println("Printing interrupted");
}
System.out.println("Print completed");
}
}

A test class named “Tester” should be created inorder to test the Before Advice samples and it should looks like the below,

Listing 5 – Tester.java


package com.sample.aop.test;

import com.sample.aop.advice.Sample;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* @author giftsam
*/
public class Tester
{
public static void main(String[] args)
{
ApplicationContext context = new ClassPathXmlApplicationContext(
"classpath:./META-INF/adviceContext.xml");
Sample sample = (Sample) context.getBean("sampleBean");
sample.printValue();
}
}

When the preceding test class is executed, the outcome will be like the below,

Output



Before Method started excuting...
Started Printing..
Print completed

Step 2 – AfterReturning
The annotation @AfterReturn is used to declare the AfterReturning advice and it executes after the implementation class “SampleImpl”(Listing 7) method “printValue”.

Listing 6 – AspectConfigBean.java


package com.sample.aop.config;

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

/**
* @author giftsam
*/
@Aspect
public class AspectConfigBean
{
@Pointcut("execution(* com.sample.aop.advice.*.*(..))")
public void adviceMethods()
{
}

@AfterReturning("adviceMethods()")
public void execute() throws Throwable
{
System.out.println("After Returning Method Executed...");
}
}

Listing 7 – SampleImpl.java


package com.sample.aop.advice;

/**
* @author giftsam
*/
public class SampleImpl implements Sample
{
public void printValue()
{
System.out.println("Started Printing.. ");
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
System.out.println("Printing interrupted");
}
System.out.println("Print completed");
}
}

The same test class named “Tester” is used to test the AfterReturning Advice samples.

Listing 8 – Tester.java


package com.sample.aop.test;

import com.sample.aop.advice.Sample;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* @author giftsam
*/
public class Tester
{
public static void main(String[] args)
{
ApplicationContext context = new ClassPathXmlApplicationContext(
"classpath:./META-INF/adviceContext.xml");
Sample sample = (Sample) context.getBean("sampleBean");
sample.printValue();
}
}

When the preceding test class is executed, the outcome will be like the below,

Output

Started Printing..
Print completed
After Returning Method Executed...

Step 3 – AfterThrowing
The annotation @AfterThrowing is used to declare the AfterThrowing advice and it runs when the implementation class “SampleImpl”(Listing 10) method “printValue” throws an exception.

Listing 9 – AspectConfigBean.java


package com.sample.aop.config;

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

/**
* @author giftsam
*/
@Aspect
public class AspectConfigBean
{
@Pointcut("execution(* com.sample.aop.advice.*.*(..))")
public void adviceMethods()
{
}

@AfterThrowing("adviceMethods()")
public void execute() throws Throwable
{
System.out.println("After Throwing Method Executed...");
}
}

Listing 10 – SampleImpl.java


package com.sample.aop.advice;

/**
* @author giftsam
*/
public class SampleImpl implements Sample
{
public void printValue()
{
System.out.println("Started Printing.. ");

String value = null;
value.toString();
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
System.out.println("Printing interrupted..");
}
System.out.println("Print completed");
}
}

The same test class named “Tester” is used to test the AfterReturning Advice samples and it should looks like the below,

Listing 11- Tester.java


package com.sample.aop.test;

import com.sample.aop.advice.Sample;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* @author giftsam
*/
public class Tester
{
public static void main(String[] args)
{
ApplicationContext context = new ClassPathXmlApplicationContext(
"classpath:./META-INF/adviceContext.xml");
Sample sample = (Sample) context.getBean("sampleBean");
sample.printValue();
}
}

When the preceding test class is executed, the outcome will be like the below,

Output

Started Printing..
After Throwing Method Executed...
Exception in thread "main" java.lang.NullPointerException

Step 4 – Around
The annotation @Around is used to declare the Around advice and it runs before or after the implementation class “SampleImpl”(Listing 13) method “printValue” executes.

Listing 12 – AspectConfigBean.java


package com.sample.aop.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

/**
* @author giftsam
*/
@Aspect
public class AspectConfigBean
{
@Pointcut("execution(* com.sample.aop.advice.*.*(..))")
public void adviceMethods()
{
}

@Around("adviceMethods()")
public void execute(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
{
long startTime = System.currentTimeMillis();
System.out.println("Around method executed..");
proceedingJoinPoint.proceed();
System.out.println("Executing completed..");
long timeTaken = System.currentTimeMillis() - startTime;
System.out.println("Execution time: " + timeTaken + " milliseconds.");
}
}

Listing 13 – SampleImpl.java


package com.sample.aop.advice;

/**
* @author giftsam
*/
public class SampleImpl implements Sample
{
public void printValue()
{
System.out.println("Started Printing.. ");
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
System.out.println("Printing interrupted..");
}
System.out.println("Print completed");
}
}

The same test class named “Tester” is used to test the Around Advice samples and it should looks like the below,

Listing 14 – Tester.java


package com.sample.aop.test;

import com.sample.aop.advice.Sample;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* @author giftsam
*/
public class Tester
{
public static void main(String[] args)
{
ApplicationContext context = new ClassPathXmlApplicationContext(
"classpath:./META-INF/adviceContext.xml");
Sample sample = (Sample) context.getBean("sampleBean");
sample.printValue();
}
}

When the preceding test class is executed, the outcome will be like the below,

Output

Around method executed..
Started Printing..
Print completed
Executing completed..
Execution time: 2001 milliseconds.

Project Structure
The project structure of the above sample application looks like the below,

Conclusion
Its not important to use all the advice in your application. Always use the advice that meets your requirements. Thats all folks, I hope this article gives you the basic knowledge in Spring 3.0 AOP advice. If you find this article is useful for you, dont forget to leave your valuable comments. Have a joyous code day.

Categories: Java, Spring

5 Responses so far.

  1. Thanks a lot for the interesting post.

    I was wondering if you ever tried Around advice with an initialization pointcut. Does it work? are you able to return another instance of a variable? is there a possibility to change the type of the caller?

    Thumb up 2 Thumb down 2

    [Reply]

    giftsam Reply:

    Hi Ahmed,
    Thanks for your comment, and your question is substantive. I reckon we cannot return another instance of a variable. Anyways I will try out and let you know.

    Thumb up 0 Thumb down 0

    [Reply]

  2. dileep says:

    Hi Sam,
    It is one of the very clear and effective articles that I have read so far. Keep it up! Thanks.

    Well-loved. Like or Dislike: Thumb up 11 Thumb down 1

    [Reply]

    giftsam Reply:

    Hi Dileep,
    Thanks a lot for your encouraging words!!

    Thumb up 0 Thumb down 0

    [Reply]

  3. tilak says:

    I tried a simple AOP example but the aspect does not get executed. Can you please suggest why?. Here is my code:

    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;

    @Aspect
    public class QueryLoggingAspect {

    @Pointcut(value=”execution(public * *(..))”)
    public void anyPublicMethod() { }

    @Around(“anyPublicMethod()”)
    public Object log(ProceedingJoinPoint pjp) throws Throwable {
    System.out.println(“before logging query..”);
    Object ret = pjp.proceed();
    System.out.println(“after logging query..”);
    return ret;
    }
    }

    //
    public class TestDao {
    public void executeQuery(String query) {
    System.out.println(“executing query … “);
    }
    }

    //
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;

    public class QueryLoggingAspectDemo {
    public static void main(String[] args) {
    XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(
    “application-context.xml”));
    TestDao testDao = (TestDao) beanFactory
    .getBean(“testDaoBean”);
    testDao.executeQuery(“Test query”);
    }
    }

    //

    Thumb up 0 Thumb down 0

    [Reply]