Ad

Thursday, 19 March 2015

Implementing logging using spring AOP

In this post we will see how to implement the logging using spring AOP. Logging is one of the cross cutting concerns which span across the multiple layer in the application.Using Spring AOP  we don't need to write the logging statements in each and every method of the class which needs to be logged.Instead we will define the cross cutting concern which is logging in our case in a single aspect(i.e Class) and we will make this aspect to execute in and around of the matched joint point(i.e method execution in spring AOP).

Below code example will give us an better idea on this.

Employee - Class for which we like to enable the logging.
LoggingAspect - Aspect class which contains and execute the advice on the employee bean.
aop.xml - Metadata information to the spring container.
AspectTest - Class which loads the spring container and gets the employee bean from the container                         and invokes the method on it.

Employee.java

package aspect;

public class Employee {

private String id=null;

private String name=null;

private double salary=0;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

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

public double getSalary() {
return salary;
}

public void setSalary(double salary) {
this.salary = salary;
}

public Double getAnnualSalary()
{
return new Double(salary*12);
}
 
public Double decrementSalary()
{
String decValue=null;
return new Double(decValue);
}
}

LoggerAspect.java

package aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class LoggerAspect {

@Pointcut("execution(* aspect.*.*(..))")
public void selectall(){}

@Around("selectall()")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable
{
String className=joinPoint.getTarget().getClass().getName();
String methodName=joinPoint.getSignature().getName();
System.out.println("Start of the Method "+className+":"+methodName);
Object object=joinPoint.proceed();
System.out.println("End of the Method "+className+":"+methodName);
return object;
}

@AfterReturning(pointcut="selectall()",returning="retvalue")
public void AfterReturningAdvice(JoinPoint joinPoint,Object retvalue)
{
String className=joinPoint.getTarget().getClass().getName();
String methodName=joinPoint.getSignature().getName();
if(retvalue!=null)
System.out.println("Value returned from method "+className+":"+methodName+"
                is:"+retvalue);
}

@AfterThrowing(pointcut="selectall()",throwing="ex")
public void AfterThrowingAdvice(JoinPoint joinPoint,Exception ex)
{
String className=joinPoint.getTarget().getClass().getName();
String methodName=joinPoint.getSignature().getName();
System.out.println("Exception encountered in Method "+className+":"+methodName
+" and exception is:"+ex.toString());
}
}


Pointcut and JointPoints

@Pointcut - Pointcut will define the joint point i.e method execution for which the logging has to be enabled.This pattern(execution(* aspect.*.*(..))) will match any method execution  in the class of  aspect package which  contains zero or more arguments.

Types of advice- Aspect will execute the below advice on the target object i.e on employee bean.

@Around - This advice will be executed both before and after the method execution(which matches with the defined pointcut).
@AfterReturningAdvice - This advice will be executed after the method execution(which matches with the defined pointcut) is returned normally without any exception.
@AfterThrowing - This advice will be executed when the exception is returned from the method execution(which matches with the defined pointcut).

aop.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-3.0.xsd">

<aop:aspectj-autoproxy/>

<bean id ="employee" class="aspect.Employee">
<property name="id" value="E12"/>
<property name="name" value="Rahul"/>
<property name="salary" value="3120"/>
</bean>

<bean id="aspectannot" class="aspect.Aspect"/>

</beans>


AspectTest.java


package aspect;

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

public class AspectTest {

  public static void main(String[] args) {

  ApplicationContext context= new ClassPathXmlApplicationContext(new String[]{"aop.xml"});
  Employee emp= context.getBean("employee", Employee.class);
  double annualSalary=emp.getAnnualSalary();//1
  try
  {
  double decSalary=emp.decrementSalary(0);//2
  }
  catch(Exception e)
  {
 //ignore the exception
  }
  }

}


OUTPUT

Start of the Method aspect.Employee:getAnnualSalary
End of the Method aspect.Employee:getAnnualSalary
Value returned from method aspect.Employee:getAnnualSalary is:37440.0
Start of the Method aspect.Employee:decrementSalary
Exception encountered in Method aspect.Employee:decrementSalary and exception is:java.lang.NullPointerException

As we can see in the output,on each method execution of the employee bean corresponding advises was executed by the LoggerAspect.

No comments:

Post a Comment