Main Tutorials

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="https://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 : https://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="https://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 : https://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="https://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 : https://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="https://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 : https://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="https://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 : https://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 Author

author image
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

Subscribe
Notify of
122 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
JoonHo
8 years ago

I am a big fan of you

venkatesh
6 years ago
Reply to  JoonHo

thanks

raj
9 years ago

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.

Radhe Kumar
4 years ago
Reply to  raj

Spring AOP implementation uses JDK dynamic proxy to create the Proxy classes with target classes and advice invocations, these are called AOP proxy classes. We can also use CGLIB proxy by adding it as the dependency in the Spring AOP project.

m
8 years ago

thanks for u r effort.Really helpful

swapnil
10 years ago

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

Sam
6 years ago

The only place in the world where I can find complete example

Carlos Adriano Portes
6 years ago

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

Ruffy
6 years ago

Great tutorial man, everything explained.

sachindra
6 years ago

Millions of thank you

Spree
6 years ago

Thx for this post. I’ve implemented aop for logging every call to repositories methods. Every repository interface of my app extends JpaRepository, so what would be the best strategy for log my repository interface name ?I mean,i want to log myrepository.findbyone() not crudrepository.findbyone()

Thanks in advance!!
Spree

firstpostcommenter
7 years ago

Nice

Salman Kazmi
7 years ago

It helped. Thanks a lot.

Sarang Anmulwar
8 years ago

Hi, Example worked when running from main, i am using restful webservice where i need to intercept services like CustomerService which you have defined. Problem is how to invoke ?
for example i have
@Autowired CustomerService customerService;

and
customerService.printName();
in one of method
in this case it will not intercept the method.
Any Solution?

Vivek
8 years ago

My program does nor recognize the class ProxyFactoryBean ??

Vaibhav Srivastav
8 years ago

Nice Explanation it’s good for me

Thanks

Akshatha
8 years ago

Nice example. Simple and to-the-point. Helped me to get started on AOP.

Mr. foo
9 years ago

The messaje in the Around advice example of the After method Hijacked is wrong! (Before after hijacked? :P)

Souro
9 years ago

Thanks….Examples are superb and easy to understand.

Kir
9 years ago

Great example but it is not woring in my project. The interceptors are not being executed.

Purav Gandhi
9 years ago

The example is really simple yet effective. But I would like to know is there any way to only call the proxy for a specific method of the service class ?

In this case, what if I want to call the proxy method only before printURL method and not for other methods. How would that be doable ?

meeran mohideen
9 years ago

Really Adorable… Thanks for your service and effort…

Jason.H
9 years ago

Awesome? tks for the worthwhile effort !! 😀

Shashi Kumar
10 years ago

This is a very clear cut explanation , can you also explain the same using @Autowire annotation?

krishnan c
10 years ago

Thanks helped me cleared all doubts,was struggling with AspectJ annotation ,terrific and simple example!

Mukesh Kumar Saini
10 years ago

Hi mkyong,
This example is not working in Spring 3.0.5 properly

Mukesh Kumar Saini
10 years ago

Thanks,
It was a typo. It is working now

praveenambati
10 years ago

Why you not used namespace ?
xmlns:aop=”http://www.springframework.org/schema/aop”

suresh kumar
10 years ago

It’s a very good example for the AOP beginers

Thanks and Regards,
suresh kumar. somarouthu

Sankha
10 years ago

Example was nice but I still get that java.lang.ClassCastException: $Proxy0 error. Anybody got past this issue? how?

Mr Mkyong, any suggestion please?

Sankha
10 years ago

Example was nice, but I still get that java.lang.ClassCastException: $Proxy0 exception. Anybody get rid of this issue yet?
Mr Mkyong, any suggestion please?

Mayur Mistry
10 years ago

Nice and Simple example for Beginners

sijo
10 years ago

Your tutorials are very useful . Great work ….