Wednesday, November 17, 2010

Logger Example using Spring AOP

Spring AOP logger example
      AOP(Aspect Oriented Programming )
  • Aspect - General feature which we want to apply globally to our application (logging, performance monitoring, exception handling, transaction management, etc).
  • Advice - A chunk of code that is invoked during program execution, and is a piece of the logic for implementing your aspect.
  • Joinpoint - A location in the code where an advice can be executed (such as field access, method invocation , constructor invocation, etc.). Spring's built-in AOP only supports method invocation
  • Pointcut - A pointcut is a set of many joinpoints where an advice should be executed.
  • Targets/Target Objects - The objects you want to apply an aspect or set of aspects to!
Steps Involved in implementing logging using Spring AOP
Step 1 :  Write a Logger class
 package com.vels.spring.aop;

/**
 * @author velmurugan pousel
 * @project Spring AOP
 * created on Nevember 15 2010
 */

public interface Calculator {
      public double add(double a, double b);
      public double subtract(double a, double b);
      public double divide(double numerator, double denominator);
      public double multiply(double a, double b);


}
Step 2 :  Implement the calculator functionality
package com.vels.spring.aop;
 /**
 * @author velmurugan pousel
 * @project springAOP
 * created on Nov 16, 2010
 */

public class CalculatorImpl implements Calculator {

      public double add(double a, double b) {
            return (a+b);
      }

      public double divide(double numerator, double denominator) {
            if(denominator == 0){
                  throw new RuntimeException("Divide by Zero error");
            }
            return (numerator/denominator);
      }

      public double multiply(double a, double b) {
            return (a*b);
      }

      public double subtract(double a, double b) {
            return (a-b);
      }
 
}
Step 3:  Create a SpringContext.xml file(which will have all context information)
<?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-2.5.xsd">

       <bean id="calculator" class="com.vels.spring.aop.CalculatorImpl" />
      </beans>
Step 4: Write the advice class(a piece of the logic for implementing your aspect)
Method Before Advice : this advice will be called before the method execution
package com.vels.spring.aop;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;

 /**
 * @author velmurugan pousel
 * @project springAOP
 * created on Nov 16, 2010
 */


public class CalculatorLoggingBeforeAdvice implements MethodBeforeAdvice {

      public void before(Method method, Object[] args, Object target)
                  throws Throwable {
            System.out.print("Logging Before method access >>");
            System.out.print("Input Values " + method.getName() + ">>");
            for (Object arg : args) {
                  System.out.print(arg + " ");
            }
            System.out.println();

      } 

     }
     Method After Runturnig Advice : this advice will be called after the method execution
package com.vels.spring.aop;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
 /**
 * @author velmurugan pousel
 * @project springAOP
 * created on Nov 16, 2010
 */
public class CalculatorLoggingAfterAdvice implements AfterReturningAdvice{

      public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
            System.out.println("Return value "+method.getName()+">>"+returnValue);       
            System.out.println("Log after return   ");     
      }    

}
Throws Advice : This advice will be called whenever exception thrown
package com.vels.spring.aop;
import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
 /**
 * @author velmurugan pousel
 * @project springAOP
 * created on Nov 16, 2010
 */
public class CalculatorLoggingThrowsAdvice implements ThrowsAdvice{

      public void afterThrowing(Method method, Object[] args, Object target,Throwable e) throws Throwable {
            System.out.println("Exception "+method.getName()+" "+e.getMessage());
      }


      }
Step 4 : Write the util class to load the context file
package com.vels.spring.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringUtil {
      public static final ApplicationContext SPRING_CONTEXT = new ClassPathXmlApplicationContext(new String[]{"config/SpringContext.xml"});
}
Step 4: Configure all the advice in the context file
<?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-2.5.xsd">

       <bean id="calculator" class="com.vels.spring.aop.CalculatorImpl" />
       
       <bean id="loggingBeforeAdvice" class="com.vels.spring.aop.CalculatorLoggingBeforeAdvice" />
       <bean id="loggingAfterAdvice" class="com.vels.spring.aop.CalculatorLoggingAfterAdvice" />
       <bean id="loggingThrowsAdvice" class="com.vels.spring.aop.CalculatorLoggingThrowsAdvice" />
       
     
      <bean id="calculatorProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
           
            <property name="target" ref="calculator" />
             
            <property name="interceptorNames">             
                  <list>                       
                        <value>loggingBeforeAdvice</value>       
                        <value>loggingAfterAdvice</value>
                        <value>loggingThrowsAdvice</value>
                  </list>
            </property> 
      </bean>
           
</beans>

loggingBeforeAdvice advice will be executed before every method invocation on CalculatorImpl calss.
loggingAfterAdvice advice will be executed after every method invocation on CalculatorImpl calss.
loggingThrowsAdvice advice will be executed when an exception got in every method invocation on CalculatorImpl calss.
Step 5: Write a client to test the logging functionality
+package com.vels.spring.aop;

import com.vels.spring.util.SpringUtil;

 /**
 * @author velmurugan pousel
 * @project springAOP
 * created on Nov 16, 2010
 */
public class CalculatorClient {
      public static void main(String[] args) {
           
            Calculator calculator = (Calculator)SpringUtil.SPRING_CONTEXT.getBean("calculatorProxy");
            calculator.subtract(3, 2);
            calculator.multiply(2, 2);
            calculator.divide(2, 0);
             
      } 

}

Output : >>>>>>>>>>
Note : Place the config folder under src folder and include spring.jar and common-logging.jar into the classpath


5 comments: