AOP面向切面编程

作用是:分离出通用的逻辑,不重复写代码。

比如:需要在访问方法是验证是否登录,可以在每个方法之前先判断,也可以使用切片。

引入依赖

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

写一个切片

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class HttpAspect {
    @Before("execution(public * com.jimo.controller.MenController.*(..))")
    public void doBefore() {
        System.out.println("before......................");
    }

    @After("execution(public * com.jimo.controller.MenController.*(..))")
    public void doAfter() {
        System.out.println("After............................");
    }
}

里面的切片语法参考spring框架文档,这里我们拦截MenController下的所有方法。

然后随便访问一个方法,控制台会输出:

before......................
2017-03-18 15:40:40.208  INFO 7954 --- [nio-8080-exec-1] o.h.h.i.QueryTranslatorFactoryInitiator 。。。
After............................

更简洁

可以看到重复的代码是不能容忍的,可以改成:

@Pointcut("execution(public * com.jimo.controller.MenController.*(..))")
    public void log() {
    }

    @Before("log()")
    public void doBefore() {
        System.out.println("before......................");
    }

    @After("log()")
    public void doAfter() {
        System.out.println("After............................");
    }

例子

截取一些信息,比如存入日志里,注意,这里使用的spring里的logger:

import org.slf4j.Logger;
public static final Logger log = LoggerFactory.getLogger(HttpAspect.class);

    @Pointcut("execution(public * com.jimo.controller.MenController.*(..))")
    public void log() {
    }

    @Before("log()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest req = attr.getRequest();
        // url
        log.info("url={}", req.getRequestURL());
        // method
        log.info("method={}", req.getMethod());
        // ip:
        log.info("ip={}", req.getRemoteAddr());
        // class method
        log.info("class_method={}",
                joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        // args
        log.info("args={}", joinPoint.getArgs());
    }

要得到执行后的返回结果:

@AfterReturning(returning = "object", pointcut = "log()")
    public void doAfterReturning(Object object) {
        log.info("response={}", object.toString());
    }

结果:

2017-03-18 16:05:37.525  INFO 7954 --- [nio-8080-exec-1] com.jimo.aspect.HttpAspect              
 : response=[com.jimo.model.Men@2ba27094, com.jimo.model.Men@4bc0ee59]
2017-03-18 16:06:23.636  INFO 7954 --- [nio-8080-exec-3] com.jimo.aspect.HttpAspect              
 : url=http://localhost:8080/men/getAll/
2017-03-18 16:06:23.636  INFO 7954 --- [nio-8080-exec-3] com.jimo.aspect.HttpAspect              
 : method=GET
2017-03-18 16:06:23.636  INFO 7954 --- [nio-8080-exec-3] com.jimo.aspect.HttpAspect               
: ip=0:0:0:0:0:0:0:1
2017-03-18 16:06:23.636  INFO 7954 --- [nio-8080-exec-3] com.jimo.aspect.HttpAspect               
: class_method=com.jimo.controller.MenController.getAllMen
2017-03-18 16:06:23.636  INFO 7954 --- [nio-8080-exec-3] com.jimo.aspect.HttpAspect              
 : args={}
Hibernate: select men0_.id as id1_0_, men0_.age as age2_0_, men0_.name as name3_0_ from men men0_
After............................


2017-03-18 16:06:23.639  INFO 7954 --- [nio-8080-exec-3] com.jimo.aspect.HttpAspect              
 : response=[com.jimo.model.Men@6e716881, com.jimo.model.Men@3d58ac51]

results matching ""

    No results matching ""