One of the Strengths of Spring is its simplicity. Spring provides the same simplicity in programming complex AOP as well.
In this post I am trying to give two simple examples of Spring AOP implementations. one is annotation based and the another one is configuration based. annotation based approach and configuration based approach, both have their own advantages and disadvantages, as per the natural rule no solution is best for every scenario.
annotation based apporoch fits in some places and configuration based fits in some places. the selection needs to be done according to the context anyway.
I am taking simple example of printing execution start and end time for every method of a class.
For the following Business Service class using AOP we are going to mark the execution start and stop time for every method in this class
public class CalculatorService {
public int add(int x, int y){
return x+y;
}
public int sub(int x, int y){
return x-y;
}
public int mul(int x, int y){
return x*y;
}
public int div(int x, int y){
return x/y;
}
}
Approach 1 - Annotation based.
First step we need to create an advise class
import java.text.SimpleDateFormat;
import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TimeLogAdvise {
SimpleDateFormat df = new SimpleDateFormat("dd:MM:yyyy h:m:s:S");
@Pointcut("execution(* com.blogger.technoant.CalculatorService.*(..))")
public void businessMethods() {
}
@Around("businessMethods()")
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(pjp.getSignature().getName() + " Starts at "
+ df.format(new Date()));
Object obj = pjp.proceed();
System.out.println(pjp.getSignature().getName() + " Ends at "
+ df.format(new Date()));
return obj;
}
}
@Aspect - marks this class as annotation
@Pointcut - specifies the matching pattern for the pointcut
@Around - is the advise
Step 2 is creating the applicationcontext.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy />
<bean id="calculatorService" class="com.blogger.technoant.CalculatorService"/>
<bean id="timeLogAdvise" class="com.blogger.technoant.TimeLogAdvise"/>
beans>
Now the time to test the advise, following class can be used for testing
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TimeLogDemo {
public static void main(String args[]){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext.xml");
CalculatorService bc = (CalculatorService) context.getBean("calculatorService");
bc.add(8, 4);
bc.sub(8, 4);
bc.mul(8, 4);
bc.div(8, 4);
}
}
to successfully execute the program you need to include following jar files in your classpath
spring, spring-sop, commons-logging,cglib, aspectj and aspectjweaver.
Approach 2 - Annotation based
In this approach advise will be a simple POJO class and all the AOP details will go to xml.
Step 1: creating the Advise POJO (without any annotation)
import java.text.SimpleDateFormat;
import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
public class TimeLogAdvisePOJO {
SimpleDateFormat df = new SimpleDateFormat("dd:MM:yyyy h:m:s:S");
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(pjp.getSignature().getName() + " Starts at "
+ df.format(new Date()));
Object obj = pjp.proceed();
System.out.println(pjp.getSignature().getName() + " Ends at "
+ df.format(new Date()));
return obj;
}
}
This is a simple class without any annotations, here we have used only one spring class ProceedingJoinPoint to get the name of the method. If we don’t want to print the name of the method it will be a simple POJO without any Spring dependency.
Step 2: xml configuration
<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.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="calculatorService" class="com.blogger.technoant.CalculatorService"/>
<bean id="timeLogAdvise" class="com.blogger.technoant.TimeLogAdvisePOJO"/>
<aop:config>
<aop:aspect id="myAspect" ref="timeLogAdvise">
<aop:pointcut id="timeLogService"
expression="execution(* com.blogger.technoant.CalculatorService.*(..))"/>
<aop:around
pointcut-ref="timeLogService"
method="profile"/>
aop:aspect>
aop:config>
beans>
Now execute the same TimeLogDemo in the approach 1.
Please write in comments if you have any problem executing this or any clarification or further info required.
Classifications: Spring AOP Example, Spring AOP annotation example, Spring AOP XML example, spring AOP logging example, spring AOP evaluation time, Spring AOP around advise example, DateFormat example, how to format date, how to create spring aop
Hello Nilavan,
ReplyDeleteNice Article. Thanks for the info.
Currently I am aspect with annotation mode. But this is to throw exception. And I have defined the applicationContext.xml file. But I am running the application through the Ant script. Here I could not able to invoke applicationContext.xml file in my code.
Please suggest me how to proceed.