AOP概述

Spring AOP(面向方面编程)框架,用于在模块化方面的横切关注点。简单得说,它只是一个拦截器拦截一些过程,例如,当一个方法执行,Spring AOP 可以劫持一个执行的方法,在方法执行之前或之后添加额外的功能。 在Spring AOP中,有 4 种类型通知(advices)的支持: 1. 通知(Advice)之前 - 该方法执行前运行 MethodBeforeAdvice 2. 通知(Advice)返回之后 – 运行后,该方法返回一个结果 AfterReturningAdvice 3. 通知(Advice)抛出之后 – 运行方法抛出异常后,ThrowsAdvic 4. 环绕通知 – 环绕方法执行运行,结合以上这三个通知 MethodInterceptor
通常,开发过程中,人们会选择实现环绕通知。

AOP实列

实现一个AOP实列:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


import javax.servlet.http.HttpServletRequest;

@Aspect # 1.加入Aspect注解
@Component # 2.加入Component注解
public class HttpAspect {
    private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);

    # 3.加入Before注解,在controller前执行;Before的参数:execution(public * com.example.server.controller.*.*(..)表明拦截哪些控制器
    @Before("execution(public * com.example.server.controller.*.*(..))")
    public void processBefore(JoinPoint joinPoint) {
      logger.info("System controller running...");
    }

    @Before("common()")
    public void processBefore(JoinPoint joinPoint) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest httpServletRequest = requestAttributes.getRequest();

        logger.info("url={},length={},ip={},method={},class={},params={}",
                httpServletRequest.getRequestURI(),
                httpServletRequest.getContentLength(),
                httpServletRequest.getRemoteAddr(),
                httpServletRequest.getMethod(),
                joinPoint.getClass(),
                joinPoint.getArgs()
                );
    }

    # 6.调用统一的拦截方法
    @After("common()")
    public void processAfter() {
        logger.info("Process controller after.");
    }

    # 4.拦截的控制器可能用于多个场景,为了防止代码重复,可以通过@Pointcut方法定义一个统一的拦截方法
    @Pointcut("execution(public * com.example.server.controller.*.*(..))")
    public void common() {

    }

    # 7.@AfterReturning可以对Controller的返回值进行拦截
    @AfterReturning(returning = "object", pointcut = "common()")
    public void responseBefore(Object object) {
        logger.info("Response={}",object);
    }
}