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.
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.
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.
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.
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
.
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.
<?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.
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();
}
}
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
Download Source Code: spring-aop-pointcut-example-using-xml-configuration