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]