Spring AOP + AspectJ annotation example

In this tutorial, we show you how to integrate AspectJ annotation with Spring AOP framework. In simple, Spring AOP + AspectJ allow you to intercept method easily.

Common AspectJ annotations :

  1. @Before – Run before the method execution
  2. @After – Run after the method returned a result
  3. @AfterReturning – Run after the method returned a result, intercept the returned result as well.
  4. @AfterThrowing – Run after the method throws an exception
  5. @Around – Run around the method execution, combine all three advices above.
Note
For Spring AOP without AspectJ support, read this build-in Spring AOP examples.

1. Directory Structure

See directory structure of this example.

directory structure of this example

2. Project Dependencies

To enable AspectJ, you need aspectjrt.jar, aspectjweaver.jar and spring-aop.jar. See following Maven pom.xml file.

AspectJ supported since Spring 2.0
This example is using Spring 3, but the AspectJ features are supported since Spring 2.0.

File : pom.xml

<project ...>
 
	<properties>
		<spring.version>3.0.5.RELEASE</spring.version>
	</properties>
 
	<dependencies>
 
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
 
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
 
		<!-- Spring AOP + AspectJ -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${spring.version}</version>
		</dependency>
 
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.6.11</version>
		</dependency>
 
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.6.11</version>
		</dependency>
 
	</dependencies>
</project>

3. Spring Beans

Normal bean, with few methods, later intercept it via AspectJ annotation.

package com.mkyong.customer.bo;
 
public interface CustomerBo {
 
	void addCustomer();
 
	String addCustomerReturnValue();
 
	void addCustomerThrowException() throws Exception;
 
	void addCustomerAround(String name);
}
package com.mkyong.customer.bo.impl;
 
import com.mkyong.customer.bo.CustomerBo;
 
public class CustomerBoImpl implements CustomerBo {
 
	public void addCustomer(){
		System.out.println("addCustomer() is running ");
	}
 
	public String addCustomerReturnValue(){
		System.out.println("addCustomerReturnValue() is running ");
		return "abc";
	}
 
	public void addCustomerThrowException() throws Exception {
		System.out.println("addCustomerThrowException() is running ");
		throw new Exception("Generic Error");
	}
 
	public void addCustomerAround(String name){
		System.out.println("addCustomerAround() is running, args : " + name);
	}
}

4. Enable AspectJ

In Spring configuration file, put “<aop:aspectj-autoproxy />“, and define your Aspect (interceptor) and normal bean.

File : Spring-Customer.xml

<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="customerBo" class="com.mkyong.customer.bo.impl.CustomerBoImpl" />
 
	<!-- Aspect -->
	<bean id="logAspect" class="com.mkyong.aspect.LoggingAspect" />
 
</beans>

4. AspectJ @Before

In below example, the logBefore() method will be executed before the execution of customerBo interface, addCustomer() method.

Note
AspectJ “pointcuts” is used to declare which method is going to intercept, and you should refer to this Spring AOP pointcuts guide for full list of supported pointcuts expressions.

File : LoggingAspect.java

package com.mkyong.aspect;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
 
@Aspect
public class LoggingAspect {
 
	@Before("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))")
	public void logBefore(JoinPoint joinPoint) {
 
		System.out.println("logBefore() is running!");
		System.out.println("hijacked : " + joinPoint.getSignature().getName());
		System.out.println("******");
	}
 
}

Run it

	CustomerBo customer = (CustomerBo) appContext.getBean("customerBo");
	customer.addCustomer();

Output

logBefore() is running!
hijacked : addCustomer
******
addCustomer() is running

5. AspectJ @After

In below example, the logAfter() method will be executed after the execution of customerBo interface, addCustomer() method.

File : LoggingAspect.java

package com.mkyong.aspect;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;
 
@Aspect
public class LoggingAspect {
 
	@After("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))")
	public void logAfter(JoinPoint joinPoint) {
 
		System.out.println("logAfter() is running!");
		System.out.println("hijacked : " + joinPoint.getSignature().getName());
		System.out.println("******");
 
	}
 
}

Run it

	CustomerBo customer = (CustomerBo) appContext.getBean("customerBo");
	customer.addCustomer();

Output

addCustomer() is running 
logAfter() is running!
hijacked : addCustomer
******

6. AspectJ @AfterReturning

In below example, the logAfterReturning() method will be executed after the execution of customerBo interface, addCustomerReturnValue() method. In addition, you can intercept the returned value with the “returning” attribute.

To intercept returned value, the value of the “returning” attribute (result) need to be same with the method parameter (result).

File : LoggingAspect.java

package com.mkyong.aspect;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
 
@Aspect
public class LoggingAspect {
 
   @AfterReturning(
      pointcut = "execution(* com.mkyong.customer.bo.CustomerBo.addCustomerReturnValue(..))",
      returning= "result")
   public void logAfterReturning(JoinPoint joinPoint, Object result) {
 
	System.out.println("logAfterReturning() is running!");
	System.out.println("hijacked : " + joinPoint.getSignature().getName());
	System.out.println("Method returned value is : " + result);
	System.out.println("******");
 
   }
 
}

Run it

	CustomerBo customer = (CustomerBo) appContext.getBean("customerBo");
	customer.addCustomerReturnValue();

Output

addCustomerReturnValue() is running 
logAfterReturning() is running!
hijacked : addCustomerReturnValue
Method returned value is : abc
******

7. AspectJ @AfterReturning

In below example, the logAfterThrowing() method will be executed if the customerBo interface, addCustomerThrowException() method is throwing an exception.

File : LoggingAspect.java

package com.mkyong.aspect;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
 
@Aspect
public class LoggingAspect {
 
   @AfterThrowing(
      pointcut = "execution(* com.mkyong.customer.bo.CustomerBo.addCustomerThrowException(..))",
      throwing= "error")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
 
	System.out.println("logAfterThrowing() is running!");
	System.out.println("hijacked : " + joinPoint.getSignature().getName());
	System.out.println("Exception : " + error);
	System.out.println("******");
 
    }
}

Run it

	CustomerBo customer = (CustomerBo) appContext.getBean("customerBo");
	customer.addCustomerThrowException();

Output

addCustomerThrowException() is running 
logAfterThrowing() is running!
hijacked : addCustomerThrowException
Exception : java.lang.Exception: Generic Error
******
Exception in thread "main" java.lang.Exception: Generic Error
	//...

8. AspectJ @Around

In below example, the logAround() method will be executed before the customerBo interface, addCustomerAround() method, and you have to define the “joinPoint.proceed();” to control when should the interceptor return the control to the original addCustomerAround() method.

File : LoggingAspect.java

package com.mkyong.aspect;
 
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
 
@Aspect
public class LoggingAspect {
 
   @Around("execution(* com.mkyong.customer.bo.CustomerBo.addCustomerAround(..))")
   public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
 
	System.out.println("logAround() is running!");
	System.out.println("hijacked method : " + joinPoint.getSignature().getName());
	System.out.println("hijacked arguments : " + Arrays.toString(joinPoint.getArgs()));
 
	System.out.println("Around before is running!");
	joinPoint.proceed(); //continue on the intercepted method
	System.out.println("Around after is running!");
 
	System.out.println("******");
 
   }
 
}

Run it

	CustomerBo customer = (CustomerBo) appContext.getBean("customerBo");
	customer.addCustomerAround("mkyong");

Output

logAround() is running!
hijacked method : addCustomerAround
hijacked arguments : [mkyong]
Around before is running!
addCustomerAround() is running, args : mkyong
Around after is running!
******

Conclusion

It’s always recommended to apply the least power AsjectJ annotation. It’s rather long article about AspectJ in Spring. for further explanations and examples, please visit the reference links below.

Anti annotation or using JDK 1.4 ?
No worry, AspectJ supported XML configuration also, read this Spring AOP + AspectJ XML example.

Download Source Code

Download it – Spring3-AOP-AspectJ-Example.zip (8 KB)

References

  1. AspectJ programming guide
  2. Spring AOP + AspectJ reference
Tags :

About the Author

mkyong
Founder of Mkyong.com and HostingCompass.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

  • Mark

    Please fix the section title on the page http://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/. The correct section title “7. AspectJ @AfterThrowing”

  • http://www.velocitypartners.net Marcello Zanelli

    Great tutorial! :D

  • vijay

    Thanks for putting all this together.

    I have a one question in spring transaction management AOP is used and following XML configuration is used to manage transaction.

    I don’t see any pointcut (Before/after/AfterReturning/AfterThrowing/Around) like . Please help me out to understand that how this transaction advise executes.

    Thanks

  • http://websitedetective.net/dn/engageonline.co.nz Disabled Dating Service

    I do believe all of the ideas you’ve introduced for your post. They’re very convincing and can certainly work.

    Still, the posts are too brief for beginners. May you please extend them a bit from next time?

    Thanks for the post.

  • hzxlb910

    good,thanks

  • Cristian Daniel Ortiz

    Hi i am a completely newbie in AOP what if i need to to fill some fields in a class before call another method some flags (update,delete,save) i use beforeAdvice

    @Before(“execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))”)
    public void logBefore(JoinPoint joinPoint)
    {

    System.out.println(“logBefore() is running!”);
    System.out.println(“hijacked : ” + joinPoint.getSignature().getName());
    System.out.println(“******”);
    }

    and the method receives a parameter example

    DAO.Student.update(Student studenToBeUpdated)

    how can i access the Student to apply my flags befored saved??

  • Abhijit

    There is very blog explain in very lucid manner to understand newbie
    Keep it good work!
    Thanks a lot :)

  • Ram

    7. AspectJ @AfterReturning should be 7. AspectJ @AfterThrowing

  • Vinod Maladkar

    Very good blog and nice example.

  • jagan

    Hi Kyoung,

    First of all, thanks a lot for publishing all this valuable information and aggregating on 1 web site. I visit your site frequently to clarify my knowledge. Now i have 1 question and the scenario is as follows:
    org.abc.xyz.service.CounterService.activeCount()
    and this service will be invoked from 2 execution paths:
    1. org.abc.xyx.controllers.ABCController and
    2. org.abc.xyz.controllers.XYZController

    Now my question is can we have an aspect on activeCount for the execution path:- ABCController–>CounterService

    thanks,
    jagan

  • Greg

    I have a question… how can these aspects work when the methods are called without it getting the instance from a bean…. As in…

    Right now it works like this…
    CustomerBo customer = (CustomerBo) appContext.getBean(“customerBo”);
    customer.addCustomerAround(“mkyong”);

    I want it make it work like this….
    CustomerBo customer = new CustomerBoImpl();
    customer.addCustomerAround(“mkyong”);

  • http://www.statsaholic.com Look

    Its such as you read my mind! You appear to know a
    lot about this, such as you wrote the e-book in it or something.
    I think that you simply can do with some percent to drive the message home a bit, but instead
    of that, that is great blog. An excellent read. I’ll certainly be back.

  • http://jaykhimani.blogspot.com Jay Khimani

    Thanks for sharing this concise tutorial. It was a great help. One question. Is there a way to define an aspect which intercepts annotated fields? For e.g. If I’ve below class

    package com.jak.sandbox.aspect;
     
    public class MyClass {
         @MyAnnotation
         private String myField;
     
         public void doSomething() {
              System.out.println(&quot;Saving the world&quot;);
         }
    }

    Now is it possible to define an aspect which will intercept the the field

    myField

    and invoke pointcut?

  • http://Nowebsite Himkar Dwivedi

    hi,
    this is really gr8 tutorial, I just follow all the steps and work fine for me, but I am facing issue in point number 6.

    I have a DAO class which has two method, addUser(user) and List getAllUsers() and I have one test call which create an user, add this user to db using DAO addUser method and after that it retrieve it.

    this unit test class works fine without adding this process, but if I add this, its giving error while retrieving the values I am getting null user list in Test class while in DAO class same list has one user.

    I am not able to figure it out how this user is getting destroyed in logging class. even in logging class itself the return value is null inside

    @AfterReturning(pointcut = &quot;execution(* po.hike.dao..*.*(..))&quot;, returning = &quot;result&quot;)
    	public void logAfterReturning(JoinPoint joinPoint, Object result) {
     
    		System.out.println(&quot;logAfterReturning() is running!&quot;);
    		System.out.println(&quot;hijacked : &quot; + joinPoint.getSignature().getName());
    		System.out.println(&quot;Method returned value is : &quot; + result);
    		System.out
    				.println(&quot;***************************************************&quot;);
     
    	}

    method

    Please help me to find the issue

    Thanks

    • http://Nowebsite Himkar Dwivedi

      even if I remove this method from “DaoLoggingAspect” class, I am getting same issue

    • http://Nowebsite Himkar Dwivedi

      the main problem is with the around function, after removing around it works fine. but still I don’t know why around cause issue her

  • Shanmugapriya

    Really an excellent example. Thank you very much.

  • http://www.miguelgbiedma.com Miguel

    Thanks a lot. As always, straight to the point. Awesome tutorial.

  • yout

    thanks, it is helpful.

    btw,?????????

    7. AspectJ @AfterReturning
    

    ???

    7. AspectJ @AfterThrowing
    
  • Kapil

    Thanks

  • Scott

    7. AspectJ @AfterReturning -> @AfterThrowing

    Great tutorial anyway!!!

  • Mohsin

    Nice work Mkyong,

    I have tried your example it is working fine in Tomcat but not working in Websphere and not getting any exception.

    I am using below jars for AOP.
    aopalliance-1.0.jar
    aspectjtools-1.5.3.jar
    spring-aop-3.0.5.RELEASE.jar
    cglib-nodep-2.1_3.jar

    kindly advice me why it is not working in Websphere 6.1

    • http://www.mkyong.com mkyong

      WebSphere products are all weird, and always have its own IBM standard. Advice is consult WebSphere document for AOP support, or call IBM :)

      • Ravishankar

        I have a quick question for you at the moment.

        How can we use Spring AOP along with AspectJ for static methods. If possible, can you show an example.

        Thanks in advance :).

  • Vinicius

    Great Post and Awesome blog by the way.

    Vinicius

  • Ravishankar

    Hi Young,

    You have posted a great tutorial regarding the usage of Spring AOP along with AspectJ. Great work, we are looking forward for more articles from you.

    I have a quick question for you at the moment.

    How can we use Spring AOP along with AspectJ for static methods. If possible, can you show an example.

    Thanks in advance :).

  • Daniel Peña

    Nice work Mkyong, I suggest avoid xml configuration in bean aspect definition , you can annotate your class as @Configurable and Spring will add it to context:

    import org.springframework.beans.factory.annotation.Configurable;

    @Configurable
    @Aspect
    public class LoggingAspect {
    ….
    }

    I hope you help.
    Regards

    • alex

      I am sorry for my questio, i am just trying to set up logger through spring aspect annotations,do you you mean in case a make my aspect class @configurable there is no need for config.xml? Thank you

  • Drago M. Petit

    Outstanding tutorial to get started with Spring AOP, thank’s a lot !

  • Matthew

    Anyway to dynamically set the value of aspectj annotation within a java class instead of “hard wired” during compilation time?

    @Pointcut(“execution(public * *(..))”)
    This seem to be promising, but if this can be dynamically set during runtime of the program without restarting the JVM, it would be really nice.

  • Pankaj Soni

    Nice work

    I think one heading is typed incorrect by mistake.
    So, Please correct the heading in
    7. AspectJ @AfterReturning => 7. AspectJ @AfterThrowing

    I would like to suggest that you have used only

      &lt;b&gt;execution&lt;/b&gt;

    in the examples.
    So, you can also show how to broaden the scope for pointcut. For example using

      &lt;b&gt;within&lt;/b&gt;

    like

    @Pointcut(&quot;execution(public * *(..))&quot;)
        private void anyPublicOperation() {}
     
        @Pointcut(&quot;within(com.xyz.someapp.trading..*)&quot;)
        private void inTrading() {}
     
        @Pointcut(&quot;anyPublicOperation() &amp;&amp; inTrading()&quot;)
        private void tradingOperation() {}
  • dileep

    Great Article, mkyong. Thanks for saving us lot of time !

  • Navneet Ranjan

    Can we apply Spring AOP with AspectJ to class which is outside Spring context but part of the same web project?Please reply with spring 3.1.1.

  • Muhammad

    Please correct Point 7 heading “AspectJ @AfterReturning” to “AspectJ @AfterThrowing”.

    Good Work!

  • Ramkumar

    is possible to apply AspectJ on Bean Using Annotations. I have to capture entry and exit point of Bean Method.

    Ramkumar

  • Michael

    Hi MKYong,

    On second thought, I think you can write book “Head First Spring”, please contact http://headfirstlabs.com/. Possibly you can make a million $ there -:)

    Michael

  • Pingback: Spring AOP + AspectJ in XML configuration example()

  • Pingback: Spring AOP Example – Advice()