Thursday, November 21, 2013

Spring AOP + AspectJ: Before and After

Spring AOP (Aspect-oriented programming) framework is used to modularize cross-cutting concerns in aspects. Put it simple, it’s just an interceptor to intercept some processes, for example, when a method is execute, Spring AOP can hijack the executing method, and add extra functionality before or after the method execution.
In Spring AOP, 4 type of advices are supported :
  • Before advice – Run before the method execution
  • After returning advice – Run after the method returns a result
  • After throwing advice – Run after the method throws an exception
  • Around advice – Run around the method execution, combine all three advices above.

Spring AOP Advices

package com.fpt.aop.pointcut;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class SearchEngineeAfterPointcut{
    private static final org.slf4j.Logger LOGGER = LoggerFactory
            .getLogger(SearchEngineeAfterPointcut.class);


    /**
     * Define pointcut inline for any of the advices
     * 

     * http://www.tutorialspoint.com/spring/aspectj_based_aop_appoach.htm
     * 

     * @param joinPoint
     * @throws Throwable
     */

    @After("within(com.fpt.controller..*) && execution(* *(..,@org.springframework.web.bind.annotation.PathVariable (*),..))")
    public void checkAfterPointCut(JoinPoint joinPoint) throws Throwable {
        // get method arguments

        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            LOGGER.debug("AFTER: checkAfterPointCut:{}",i);
        }
    }
}


package com.fpt.aop.pointcut;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class SearchEngineeBeforePointcut{

    private static final org.slf4j.Logger LOGGER = LoggerFactory
            .getLogger(SearchEngineeBeforePointcut.class);

    /**
     * Define pointcut inline for any of the advices
     * 

     * http://www.tutorialspoint.com/spring/aspectj_based_aop_appoach.htm
     * 

     * @param joinPoint
     * @throws Throwable
     */


    @Before("within(com.fpt.controller..*) && execution(* *(..,@org.springframework.web.bind.annotation.PathVariable (*),..))")
    public void checkBeforePointCut(JoinPoint joinPoint) throws Throwable {    

        // get method arguments

        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            LOGGER.debug("BEFORE: checkBeforePointCut:{}",i);
        }
    }
}


Spring MVC

package com.fpt.controller;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.fpt.domain.Person;
import com.fpt.domain.PersonList;
import com.fpt.service.PersonService;

@Controller
public class RestController {
    protected static Logger logger = Logger.getLogger(RestController.class);

    @Autowired
    private PersonService personService;

    // http://localhost:8080/spring-aop-search/mvc/persons

    @RequestMapping(value = "/persons", method = RequestMethod.GET, headers = "Accept=application/xml, application/json")
    public @ResponseBody
    PersonList getPerson() {
        logger.debug("Provider has received request to get all persons");
        PersonList result = new PersonList();
        result.setData(personService.getAllPerson());
        return result;
    }

    // http://localhost:8080/spring-aop-search/mvc/person/1

    @RequestMapping(value = "/person/{id}", method = RequestMethod.GET, headers = "Accept=application/xml, application/json")
    public @ResponseBody
    Person getPerson(@PathVariable("id") Long id) {
        logger.debug("Provider has received request to get person with id: "
                + id);
        return personService.getPerson(id);
    }

    // http://localhost:8080/spring-aop-search/mvc/person

    @RequestMapping(value = "/person", method = RequestMethod.POST, headers = "Accept=application/xml, application/jsonp")
    public @ResponseBody
    Person addPerson(@RequestBody Person person) {
        logger.debug("Provider has received request to add new person");
        if (person.getFirstName() == null)
            throw new NullPointerException("First Name can not be null");
        return personService.addPerson(person);
    }
}


Source Code