Tuesday, August 12, 2014

Spring Annotations AOP

Spring supports AOP by using ((Annotation)). Let's write an advice which will print a message before and after a HelloWorld program. Let's assume HelloWorld has a printMessage function.

Aspect class : AroundHelloWorldDecorator 

//Annotation to mark that this is an aspect class
@Aspect
public class AroundHelloWorldDecorator{
    
   //Around advice with pointcut which says that this advice needs to be applied to 

 //any method execution whose name is printMessage, can have any number and
   //type of argument and can have any return type
   @Around("execution(* printMessage(..))")
   public Object appendMessages(ProceedingJoinPoint pjp) throws Throwable{
            System.out.print("OyeJava says ");
           Object obj = pjp.proceed();
             System.out.println(" I am here with Annotations");
            return obj;
  }
}

Do the following changes in context.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-2.5.xsd
    http://www.springframework.org/schema/aop 
      http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
      
      <!-- Enables the aspectJ support in spring -->
      <aop:aspectj-autoproxy />
      
      <!-- Register the advice class  -->
      <bean class="AroundHelloWorldDecorator"/>
      
    <bean id="helloWorld" class="HelloWorld"/>
</beans>

Note that we are not doing any change to our HelloWorld. Now again get the class from main method. Again notice that there is no change in the main method:

String[] files = {"context.xml"};
ApplicationContext appContext = new ClassPathXmlApplicationContext(files);
        
HelloWorld helloWorld = (HelloWorld)appContext.getBean("helloWorld");
helloWorld.printMessage();

Notice in the console what you get printed.

It is possible to separate out the advice and the pointcut which increases the reusability. For that modify the aspect class as follows:

@Aspect
public class AroundHelloWorldDecorator {
    
   //Defining the pointcut separately. The method has no meaning. It just acts
   //as a placeholder to put the annotation. The restrictions comes because in
   //Java you cannot hand the annotation anywhere.
   @Pointcut("execution(* printMessage(..))")    
   void printMessagePointCut(){}
    
   @Around("printMessagePointCut()")
   public Object pointcutMessage(ProceedingJoinPoint pjp)
    throws Throwable{
    System.out.print("Pointcut defined separately ");
    Object obj = pjp.proceed();
    return obj;
  }

No comments:

Post a Comment