Spring AOP Example – Advice

Spring AOP + AspectJ
Using AspectJ is more flexible and powerful, please refer to this tutorial – Using AspectJ annotation in Spring AOP.

Spring AOP (Aspect-oriented programming) framework is used to modularize cross-cutting concerns in aspects. Put it simple, it’s just an interceptor to intercept some processes, for example, when a method is execute, Spring AOP can hijack the executing method, and add extra functionality before or after the method execution.

In Spring AOP, 4 type of advices are supported :

  • Before advice – Run before the method execution
  • After returning advice – Run after the method returns a result
  • After throwing advice – Run after the method throws an exception
  • Around advice – Run around the method execution, combine all three advices above.

Following example show you how Spring AOP advice works.

Simple Spring example

Create a simple customer service class with few print methods for demonstration later.


package com.mkyong.customer.services;

public class CustomerService {
	private String name;
	private String url;

	public void setName(String name) {
		this.name = name;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public void printName() {
		System.out.println("Customer name : " + this.name);
	}

	public void printURL() {
		System.out.println("Customer website : " + this.url);
	}

	public void printThrowException() {
		throw new IllegalArgumentException();
	}

}

File : Spring-Customer.xml – A bean configuration file


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

	<bean id="customerService" class="com.mkyong.customer.services.CustomerService">
		<property name="name" value="Yong Mook Kim" />
		<property name="url" value="http://www.mkyong.com" />
	</bean>

</beans>

Run it


package com.mkyong.common;

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

import com.mkyong.customer.services.CustomerService;

public class App {
	public static void main(String[] args) {
		ApplicationContext appContext = new ClassPathXmlApplicationContext(
				new String[] { "Spring-Customer.xml" });

		CustomerService cust = (CustomerService) appContext.getBean("customerService");

		System.out.println("*************************");
		cust.printName();
		System.out.println("*************************");
		cust.printURL();
		System.out.println("*************************");
		try {
			cust.printThrowException();
		} catch (Exception e) {

		}

	}
}

Output


*************************
Customer name : Yong Mook Kim
*************************
Customer website : http://www.mkyong.com
*************************

A simple Spring project to DI a bean and output some Strings.

Spring AOP Advices

Now, attach Spring AOP advices to above customer service.

1. Before advice

It will execute before the method execution. Create a class which implements MethodBeforeAdvice interface.


package com.mkyong.aop;

import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;

public class HijackBeforeMethod implements MethodBeforeAdvice
{
	@Override
	public void before(Method method, Object[] args, Object target)
		throws Throwable {
	        System.out.println("HijackBeforeMethod : Before method hijacked!");
	}
}

In bean configuration file (Spring-Customer.xml), create a bean for HijackBeforeMethod class , and a new proxy object named ‘customerServiceProxy‘.

  • ‘target’ – Define which bean you want to hijack.
  • ‘interceptorNames’ – Define which class (advice) you want to apply on this proxy /target object.

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

	<bean id="customerService" class="com.mkyong.customer.services.CustomerService">
		<property name="name" value="Yong Mook Kim" />
		<property name="url" value="http://www.mkyong.com" />
	</bean>

	<bean id="hijackBeforeMethodBean" class="com.mkyong.aop.HijackBeforeMethod" />

	<bean id="customerServiceProxy" 
                 class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />

		<property name="interceptorNames">
			<list>
				<value>hijackBeforeMethodBean</value>
			</list>
		</property>
	</bean>
</beans>
Note
To use Spring proxy, you need to add CGLIB2 library. Add below in Maven pom.xml file.


	<dependency>
		<groupId>cglib</groupId>
		<artifactId>cglib</artifactId>
		<version>2.2.2</version>
	</dependency>

Run it again, now you get the new customerServiceProxybean instead of the original customerService bean.


package com.mkyong.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mkyong.customer.services.CustomerService;

public class App {
	public static void main(String[] args) {
		ApplicationContext appContext = new ClassPathXmlApplicationContext(
				new String[] { "Spring-Customer.xml" });

		CustomerService cust = 
                                (CustomerService) appContext.getBean("customerServiceProxy");

		System.out.println("*************************");
		cust.printName();
		System.out.println("*************************");
		cust.printURL();
		System.out.println("*************************");
		try {
			cust.printThrowException();
		} catch (Exception e) {

		}

	}
}

Output


*************************
HijackBeforeMethod : Before method hijacked!
Customer name : Yong Mook Kim
*************************
HijackBeforeMethod : Before method hijacked!
Customer website : http://www.mkyong.com
*************************
HijackBeforeMethod : Before method hijacked!

It will run the HijackBeforeMethod’s before() method, before every customerService’s methods are execute.

2. After returning advice

It will execute after the method is returned a result. Create a class which implements AfterReturningAdvice interface.


package com.mkyong.aop;

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;

public class HijackAfterMethod implements AfterReturningAdvice
{
	@Override
	public void afterReturning(Object returnValue, Method method,
		Object[] args, Object target) throws Throwable {
	        System.out.println("HijackAfterMethod : After method hijacked!");
	}
}

Bean configuration file


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

	<bean id="customerService" class="com.mkyong.customer.services.CustomerService">
		<property name="name" value="Yong Mook Kim" />
		<property name="url" value="http://www.mkyong.com" />
	</bean>

	<bean id="hijackAfterMethodBean" class="com.mkyong.aop.HijackAfterMethod" />

	<bean id="customerServiceProxy" 
                class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />

		<property name="interceptorNames">
			<list>
				<value>hijackAfterMethodBean</value>
			</list>
		</property>
	</bean>
</beans>

Run it again, Output


*************************
Customer name : Yong Mook Kim
HijackAfterMethod : After method hijacked!
*************************
Customer website : http://www.mkyong.com
HijackAfterMethod : After method hijacked!
*************************

It will run the HijackAfterMethod’s afterReturning() method, after every customerService’s methods that are returned result.

3. After throwing advice

It will execute after the method throws an exception. Create a class which implements ThrowsAdvice interface, and create a afterThrowing method to hijack the IllegalArgumentException exception.


package com.mkyong.aop;

import org.springframework.aop.ThrowsAdvice;

public class HijackThrowException implements ThrowsAdvice {
	public void afterThrowing(IllegalArgumentException e) throws Throwable {
		System.out.println("HijackThrowException : Throw exception hijacked!");
	}
}

Bean configuration file


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

	<bean id="customerService" class="com.mkyong.customer.services.CustomerService">
		<property name="name" value="Yong Mook Kim" />
		<property name="url" value="http://www.mkyong.com" />
	</bean>

	<bean id="hijackThrowExceptionBean" class="com.mkyong.aop.HijackThrowException" />

	<bean id="customerServiceProxy" 
                 class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />

		<property name="interceptorNames">
			<list>
				<value>hijackThrowExceptionBean</value>
			</list>
		</property>
	</bean>
</beans>

Run it again, output


*************************
Customer name : Yong Mook Kim
*************************
Customer website : http://www.mkyong.com
*************************
HijackThrowException : Throw exception hijacked!

It will run the HijackThrowException’s afterThrowing() method, if customerService’s methods throw an exception.

4. Around advice

It combines all three advices above, and execute during method execution. Create a class which implements MethodInterceptor interface. You have to call the “methodInvocation.proceed();” to proceed on the original method execution, else the original method will not execute.


package com.mkyong.aop;

import java.util.Arrays;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class HijackAroundMethod implements MethodInterceptor {
	@Override
	public Object invoke(MethodInvocation methodInvocation) throws Throwable {

		System.out.println("Method name : "
				+ methodInvocation.getMethod().getName());
		System.out.println("Method arguments : "
				+ Arrays.toString(methodInvocation.getArguments()));

		// same with MethodBeforeAdvice
		System.out.println("HijackAroundMethod : Before method hijacked!");

		try {
			// proceed to original method call
			Object result = methodInvocation.proceed();

			// same with AfterReturningAdvice
			System.out.println("HijackAroundMethod : Before after hijacked!");

			return result;

		} catch (IllegalArgumentException e) {
			// same with ThrowsAdvice
			System.out.println("HijackAroundMethod : Throw exception hijacked!");
			throw e;
		}
	}
}

Bean configuration file


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

	<bean id="customerService" class="com.mkyong.customer.services.CustomerService">
		<property name="name" value="Yong Mook Kim" />
		<property name="url" value="http://www.mkyong.com" />
	</bean>

	<bean id="hijackAroundMethodBean" class="com.mkyong.aop.HijackAroundMethod" />

	<bean id="customerServiceProxy" 
                class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />

		<property name="interceptorNames">
			<list>
				<value>hijackAroundMethodBean</value>
			</list>
		</property>
	</bean>
</beans>

Run it again, output


*************************
Method name : printName
Method arguments : []
HijackAroundMethod : Before method hijacked!
Customer name : Yong Mook Kim
HijackAroundMethod : Before after hijacked!
*************************
Method name : printURL
Method arguments : []
HijackAroundMethod : Before method hijacked!
Customer website : http://www.mkyong.com
HijackAroundMethod : Before after hijacked!
*************************
Method name : printThrowException
Method arguments : []
HijackAroundMethod : Before method hijacked!
HijackAroundMethod : Throw exception hijacked!

It will run the HijackAroundMethod’s invoke()method, after every customerService’s method execution.

Conclusion

Most of the Spring developers are just implements the ‘Around advice ‘, since it can apply all the advice type, but a better practice should choose the most suitable advice type to satisfy the requirements.

Pointcut
In this example, all the methods in a customer service class are intercepted (advice) automatically. But for most cases, you may need to use Pointcut and Advisor to intercept a method via it’s method name.

Download Source Code

Download it – Spring-AOP-Advice-Examples.zip (8 KB)

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

avatar
107 Comment threads
22 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
117 Comment authors
Radhe KumarSamCarlos Adriano PortesRuffyvenkatesh Recent comment authors
newest oldest most voted
JoonHo
Guest
JoonHo

I am a big fan of you

raj
Guest
raj

I did not add cglib dependency in my pom but all the examples on this page worked for me. Can anyone explainthe role of cglib why all examples worked without cglib? thanks in advance.

swapnil
Guest
swapnil

Thank you, this is really nice.
Quite simple and straightforward explanation to understand for new person. Thank you again.

Carlos Adriano Portes
Guest
Carlos Adriano Portes

Is it possible to register the interception without using the xml? For example when creating the application context programmatically?

m
Guest
m

thanks for u r effort.Really helpful

trackback
Spring – Auto proxy creator example | Spring

[…] creator example Written on March 28, 2010 at 1:44 am by mkyong In the last Spring AOP advice, pointcut and advisor example, you have to manually create a proxy bean (ProxyFactoryBean) for […]

trackback
Spring Tutorials | Tutorials

[…] Spring AOP Example – Advice Examples and explanations about different types of Spring’s advices. […]

B MuraliDevasena Madan Mohan Reddy
Guest
B MuraliDevasena Madan Mohan Reddy

Great tutorial.. well done.. even i didnot found in Interface 21 site also

Hands off!!!!

Sudheer
Guest
Sudheer

I read may other tutorials, but had hard time understanding AOP.
This step by step approach made it very easy to understand.
Thanks. Glad that I found mkyong’s tutorial.

Khalid
Guest
Khalid

Best AOP tutorial I have read so far. Great example with simple explaination. Great Job!!

Krishna Kumar.S
Guest
Krishna Kumar.S

Hi,

It’s a great tutorial. It was very helpful. Simple and easy to understand. Great work. You saved me from slogging for hours. I was searching for materials like this.

Once I gain sufficient knowledge about Springs, I would let you know more..

Best wishes from India,

-Krishna.

sekhar
Guest
sekhar

Thanks a lot.

Sudarsan
Guest
Sudarsan

Thanks a lot!!! Great tutorial .. Very nice examples

–Sudarsan

Siddharth
Guest
Siddharth

Very very good tutorial,this is very small but it gives basic working of advices .
Brilliant Work

kannan
Guest
kannan

great tutorial made my life very easy . trying to understand AOP for the past four days reading the entire spring material couldnt understand. But this one easy and simple . gGreat help thanks

Paul Sydney Orozco
Guest
Paul Sydney Orozco

very much helpful…

Nrithya
Guest
Nrithya

Cool Tutorial. Simple yet effective. Thanks 🙂

Manjunath
Guest
Manjunath

I am getting the error while creating the ProxyFactoryBean itself in my AOP example.

please tell me that whether i miss any jars ,The error is as follows,

Caused by: java.lang.IllegalAccessError
	at net.sf.cglib.core.ClassEmitter.setTarget(ClassEmitter.java:47)
	at net.sf.cglib.core.ClassEmitter.(ClassEmitter.java:39)
	at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:165)
	at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
	at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:215)
	at net.sf.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145)
	at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:117)
	at net.sf.cglib.core.KeyFactory.create(KeyFactory.java:108)
	at net.sf.cglib.proxy.Enhancer.(Enhancer.java:64)
	at org.springframework.aop.framework.Cglib2AopProxy.createEnhancer(Cglib2AopProxy.java:229)
	at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:171)
	... 9 more
lwpro2
Guest
lwpro2

using AspectJ annotation should be much easier.

Ashwani
Guest
Ashwani

Very Good and helpful Tutorial.

srikanth
Guest
srikanth

nice tutorial thankyou so much

Santanu interested in J2ee
Guest
Santanu interested in J2ee

Very Good Tutorial. I like it. Very helpful for me to learn AOP basic concept.

Ankit
Guest
Ankit

Brilliant Article Dude!!!!!
Keep it up
You rocks

Rachna Gupta
Guest
Rachna Gupta

Itz amazing tutorial and very simple approach to deal wid AOP..as i am unable to undersatnd concept of AOP

akki
Guest
akki

Good Example to Follow for Beginners………

sapra
Guest
sapra

Please upload examples of Spring AspectJ with annotations as they are much simpler and cleaner.

trackback
Spring AOP Example – Pointcut , Advisor

[…] last Spring AOP advice examples, all the methods in a class will be intercept automatically. But for most cases, you may need a way […]

Jitendra
Guest
Jitendra

really very nice.

Manoj Kumar Shori
Guest
Manoj Kumar Shori

Really Excellent Practical Example for newbies in Spring to get started with AOP.

Simply Hats off!! for making it so simple

trackback
Spring AOP + AspectJ annotation example

[…] execution, combine all three advices above. Note For Spring AOP without AspectJ support, read this build-in Spring AOP examples.1. Directory Structure […]