Spring AOP before advice example


Spring AOP before advice example

Before advice:

Before advice is an Advice that executes before a join point. It does not have the ability to prevent execution flow proceeding to the join point (unless it throws an exception).

There are two ways to create an Advice.
  • Annotation driven
  • XML configuration driven


Following Spring before advice example explains both the approaches.

Below screenshot shows the project structure;



In this sample application I have a Java Interface, a business class which implements the java interface,
a java class Advice, another class for annotation driven advice, a simple java class with public static void main() to drive this application.

The business class has a public method sayHello() which will get a String argument and append it with the word "Hello" and return. So if you pass 'your_name' it will return 'Hello your_name'.

Our requirement is to log the method execution without writing any logic in the business method. So I have created advices to log the method execution. Before advice runs before the method execution and logs the method name. (Here it will just print in the console).

In my ApplicationContext.xml I have created beans for BusinessClass and for the advices. <aop:config> is used to create XML driven aop configurations. <aop:pointcut> is used to define the pointcut expression and <aop:before> tells which method of the advice needs to be executed.

<aop:before pointcut-ref="logPointCut" method="log" /> In this configuration, pointcut-ref is used to match the pointcut expression we have already defined and method tells the method in the referenced advice which needs to be executed. In this example log() method is available in loggingAspect class.



<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-3.2.xsd
        http://www.springframework.org/schema/aop 
  http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
 <bean id="businessClass" class="com.sample.spring.business.BusinessClass">
 </bean>

 <bean id="loggingAspect" class="com.sample.spring.aop.LoggingAspect" />
 <bean id="loggingAspect1" class="com.sample.spring.aop.LogginAspectAnnotationDriven" />
 <aop:aspectj-autoproxy />
 <aop:config>
  <aop:aspect ref="loggingAspect">
   <aop:pointcut id="logPointCut" expression="execution(public * *(..))" />
   <aop:before pointcut-ref="logPointCut" method="log" />
  </aop:aspect>
 </aop:config>
</beans>


Below is my Business Interface;


/**
*
*/
package com.sample.spring.business;

/**
* @author Prabu
*
*/
public interface BusinessInterface {
public String sayHello(String name);
}


My Business Class implementing the interface is given below;

/**
 * 
 */
package com.sample.spring.business;

/**
 * @author Prabu
 *
 */
public class BusinessClass implements BusinessInterface {

 @Override
 public String sayHello(String name) {
  return "Hello "+name;
 }
}


Advice class for the XML driven approach is given below; it just displays the method which is being executed in the console.

/**
 * 
 */
package com.sample.spring.aop;

import org.aspectj.lang.JoinPoint;
/**
 * @author Prabu
 * 
 */
public class LoggingAspect {
 public void log(JoinPoint jp) throws Throwable {
  System.out.println("Before executing "+jp.getSignature().getName()+"()");
 }
}


Advice class for annotation driven approach is given below; this class also does the same process.
@Aspect is used to create the Advice
@Before("execution(public * *(..))") tells this method needs to be executed before the execution of any public method's execution.


/**
 * 
 */
package com.sample.spring.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * @author Prabu
 *
 */
@Aspect
public class LogginAspectAnnotationDriven {
 
 @Before("execution(public * *(..))")
 public void beforeAdvice(JoinPoint jp){
  System.out.println("Annotation driven:Before executing "+jp.getSignature().getName()+"()");
 }
}

The driver class for the application is given below which is a simple java class with public static void main(). This class creates business bean object from the ApplicationContext.xml and invokes the business method sayHello().


/**
 * 
 */
package com.sample.spring.driver;

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

import com.sample.spring.business.BusinessInterface;

/**
 * @author Prabu
 *
 */
public class AOPTester {

 /**
  * @param args
  */
 public static void main(String[] args) {
  ApplicationContext contex = new ClassPathXmlApplicationContext("ApplicationContext.xml"); 
  BusinessInterface tester=(BusinessInterface) contex.getBean("businessClass"); 
  String result=tester.sayHello("Prabu");
  System.out.println(result);
 }

}

So the XML driven advice should print "Before executing sayHello() and the annotation driven advice should print Annotation driven:Before executing sayHello() before the business method retuns 'Hello Prabu' string to the driver class.




Important thing we have to know is the business class does not aware of this interception. So the business logic is separated from the logging logic(cross-cutting concern). This logging logic will be applied to all the public methods in the application. Which means that logging code is written in only one place but will be applied to all the modules. This avoids duplication of the logging logic across the application.

          Thus we have created before advice by Annotation driven and XML configuration driven  approaches.

Source code of this application:

SpringAOPBeforeAdvice.zip





Reactions:

1 comment :

  1. Thank you for your useful post. It was nice to see both xml and annotation driven aspects and see how they work.

    ReplyDelete

Ads