目录

什么是AOP

首先什么是面向切片编程,就指是把逻辑代码和处理琐碎事务的代码分离开,以便能够分离复杂度。

实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。

但是人们也发现,在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。

也许有人会说,那好办啊,我们可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类就有耦合了,它的改变会影响这两个类。那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程

举个例子:先假设你有一段逻辑代码要写~ 在这段代码之前要写log;代码完成之后要写log。结局就是一大堆的log代码就淹没了逻辑代码。aop的想法就是将非逻辑部分的代码抽离出来,只考虑逻辑代码就行了,我把框框画好,这里写前面的log,这里写逻辑,这里写后面的log。

这里我们就用AOP来统一记录请求日志。

maven依赖

                <!--aop-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

建立处理类

比如我们要记录UserController类所有方法的请求日志。

package cn.notemi.aspect;

import com.sun.deploy.net.HttpRequest;
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;

/**
 * Title:HttpAspect
 * Description:AOP HTTP 请求
 *
 * @author Flicker
 * @create 2017-08-03 下午 11:20
 **/
@Aspect
@Component
public class HttpAspect {

    private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);

    @Pointcut("execution(public * cn.notemi.controller.UserController.*(..))")
    public void log(){
    }
    //方法前执行
    @Before("log()")
    public void doBefore(JoinPoint joinPoint){
        ServletRequestAttributes attribute = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attribute.getRequest();
        //url
        logger.info("url={}",request.getRequestURI());
        //method
        logger.info("method={}",request.getMethod());
        //ip
        logger.info("ip={}",request.getRemoteAddr());
        //类方法
        logger.info("class_method={}",joinPoint.getSignature().getDeclaringTypeName()+ "."+joinPoint.getSignature().getName());
        //参数
        logger.info("args={}",joinPoint.getArgs());
    }
    //方法后执行
    @After("log()")
    public void doAfter(){
        logger.info("2");
    }

    //获取请求结果
    @AfterReturning(returning = "object" , pointcut = "log()")
    public void doAfterReturing(Object object){
        logger.info("response={}",object.toString());
    }
}

@Pointcut是标识方法,execution(public * cn.notemi.controller.UserController.*(..))就代表标识UserController下所有的方法。

是不是很简单呢?

AOP是spring重要的特性,还有IOC,如果不理解两者的话,spring的精髓你就没领悟到,所以推荐大家学习。