Spring AOP pointcut example using XML configuration


In this tutorial, you will learn about the Spring AOP pointcut and how to apply it. Spring provided two classes StaticMethodMatcherPointcut and NameMatchMethodPointcut to implement the pointcut (condition) where the advice or service has to be executed. If you do not apply pointcut the service executed for every method.

Consider the following business class Bank that has two methods deposit and findDetails.

public class Bank{
	
	public void deposit(){
		// some logic
	}	
	
	public void findDetails(){
		// some logic
	}
}

And you want to execute the logging service only for deposit method, not for findDetails. To do that you need to apply the pointcut.

Note: Pointcut verifies the class names and method names, but not runtime parameters of the method.

Let’s see the complete example.

Business Class

The business class Bank contains two method deposit and findDetails and wanna do some logging only for deposit method.

Bank.java
package org.websparrow.business;

import org.websparrow.exception.InvalidAcNoException;

public class Bank {

	private String accountNo = "XYZ123";
	private int amount = 1000;

	public void deposit(int amount, String acNo) {

		if (acNo.equals(this.accountNo)) {

			System.out.println("inside deposit method...");

			this.amount = this.amount + amount;

			System.out.println("Total Balance: " + this.amount);

		} else {
			throw new InvalidAcNoException();
		}
	}

	public void findDetails(String acNo) {

		if (acNo.equals(this.accountNo)) {

			System.out.println("A/C Holder Name: Websparrow.org, DOB: Actober 22, 2016, A/C No: XYZ123, Location: India");

		} else {
			throw new InvalidAcNoException();
		}
	}
}

Exception Class

Handling the exception when the user entered the wrong account number.

InvalidAcNoException.java
package org.websparrow.exception;

public class InvalidAcNoException extends RuntimeException {

	private static final long serialVersionUID = 9087720614302482902L;

	@Override
	public String toString() {

		return "INVALID ACCOUNT NUMBER";
	}
}

Service Class

We want to execute the Before Advice Service only for deposit method.

LoggingService.java
package org.websparrow.service;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class LoggingService implements MethodBeforeAdvice {

	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {

		System.out.println("............I'M EXECUTED BEFORE DEPOSIT METHOD...................");

	}
}

To do that create a PointcutService class, extend it from StaticMethodMatcherPointcut and override its matches method.

PointcutService.java
package org.websparrow.service;

import java.lang.reflect.Method;

import org.springframework.aop.support.StaticMethodMatcherPointcut;

public class PointcutService extends StaticMethodMatcherPointcut {

	@Override
	public boolean matches(Method method, Class<?> targetClass) {

		String methodName = method.getName();

		if (methodName.equals("deposit")) {
			return true;
		} else {
			return false;
		}
	}
}

How to add Pointcut to the Proxy?

We know to how to add target and advice to the proxy. To add target we have setTarget method and to add service we have setInterceptorNames method.

In case if we have a pointcut, we can’t add it directly to the proxy. We need to add it to the advisor. Advisor is a combination of pointcut and advice. Spring framework provides DefaultPointcutAdvisor class. In this class, there is a setter method setAdvice and setPointcut.

Spring AOP pointcut example using XML configuration

XML Configuration

In the configuration file, instantiate the target class i.e. Bank, advice class i.e. LoggingService and pointcut class i.e. PointcutService. Add pointcut + advice to the advisor and finally add target + advisor to the proxy.

spring.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- create target -->
	<bean id="bank" class="org.websparrow.business.Bank" />

	<!-- create advice -->
	<bean id="service" class="org.websparrow.service.LoggingService" />

	<!-- create pointcut -->
	<bean id="depositPointcut" class="org.websparrow.service.PointcutService" />

	<!-- add pointcut + advice to the advisor -->
	<bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
		<property name="advice" ref="service" />
		<property name="pointcut" ref="depositPointcut" />
	</bean>

	<!-- add target + advisor to proxy -->
	<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="target" ref="bank" />
		<property name="interceptorNames">
			<list>
				<value>advisor</value>
			</list>
		</property>
	</bean>
</beans>

Run it

Create a Client class, load the configuration file and run it.

Client.java
package org.websparrow.test;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.websparrow.business.Bank;

public class Client {

	public static void main(String[] args) {

		ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

		Bank bank = (Bank) context.getBean("proxy");

		bank.deposit(500, "XYZ123");

		// bank.findDetails("XYZ123");

		context.close();
	}
}
Output:

To test it uncomment the findDetails and run it. You will notice that the logging service is not executed for the findDetails, it wil execute only for the deposit method.

A/C Holder Name: Websparrow.org, DOB: Actober 22, 2016, A/C No: XYZ123, Location: India
............I'M EXECUTED BEFORE DEPOSIT METHOD...................
inside deposit method...
Total Balance: 1500

About the Author

Atul Rai
I like sharing my experiments and ideas with everyone by writing articles on the latest technological trends.