一、AOP概念和作用
1.功能定义
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
2.常用实现功能
日志记录、权限管理等等
3.AOP核心概念
以上概念含义和关系,参考博客:
https://blog.csdn.net/q982151756/article/details/80513340
二、实现
1.实现步骤(3w)
(1)What:定义切面类
(2)Where:确定在哪里执行切面
(3)When:确定什么时候执行切面
2.添加AOP依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
3. 需要切片的controller包下的目标类TvSeriesController
package cn.devmgr.tutorial.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import cn.devmgr.tutorial.pojo.TvSeries;
import cn.devmgr.tutorial.service.TvSeriesService;
/**
* RestController的一个例子
*
*/
@RestController
@RequestMapping("/request")
public class TvSeriesController {
private final Log log = LogFactory.getLog(TvSeriesController.class);
@GetMapping("/getAllInfo")
public String getAllInfo() {
if(log.isTraceEnabled()) {
log.trace("getAllInfo() ");
}
String ret="This is getAllInfo() function";
return ret;
}
}
4.切片类RequestLogAspect
(1)步骤
第一步,添加注解
@Aspect
@Component
第二步,指定Aspect切入点
//切入点
@Pointcut("execution(public * cn.devmgr.tutorial.controller.*.*(..))")
public void ControllerPointcutLog(){}
备注execution解释:
execution(方法修饰符 返回参数类型 包名.类名.方法(方法参数))
其中:
*代表所有
..代表方法参数不确定
第三步,指定切入时机
//切点之前
@Before("ControllerPointcutLog()")
public void doBeforeLog(JoinPoint joinPoint){
//切点之后
@AfterReturning(returning = "ret",pointcut = "ControllerPointcutLog()")
public void doAfterLog(Object ret){
(2)代码
package cn.devmgr.tutorial.springAOP;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
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
@Component
public class RequestLogAspect {
private static final Logger logger= LoggerFactory.getLogger(RequestLogAspect.class);//LogFactory.getLog(RequestLogAspect.class);
//切入点
@Pointcut("execution(public * cn.devmgr.tutorial.controller.*.*(..))")
public void ControllerPointcutLog(){}
//何时操作
@Before("ControllerPointcutLog()")
public void doBeforeLog(JoinPoint joinPoint){
//接受请求,记录请求信息
// SerletRequestAttributes
ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request=attributes.getRequest();
//记录下请求内容
logger.info("URL :"+request.getRequestURL().toString());
logger.info("IP :"+request.getRemoteAddr());
}
@AfterReturning(returning = "ret",pointcut = "ControllerPointcutLog()")
public void doAfterLog(Object ret){
//处理请求,返回内容
logger.info("RESPONSE IS : "+ret);
}
}
3.测试结果
(1)界面访问:http://localhost:8080/request/getAllInfo
(2)日志
2019-12-16 19:01:17.726 INFO 25896 --- [nio-8080-exec-1] c.d.tutorial.springAOP.RequestLogAspect : URL :http://localhost:8080/request/getAllInfo
2019-12-16 19:01:17.727 INFO 25896 --- [nio-8080-exec-1] c.d.tutorial.springAOP.RequestLogAspect : IP :0:0:0:0:0:0:0:1
2019-12-16 19:01:17.730 TRACE 25896 --- [nio-8080-exec-1] c.d.t.controller.TvSeriesController : getAllInfo()
2019-12-16 19:01:17.730 INFO 25896 --- [nio-8080-exec-1] c.d.tutorial.springAOP.RequestLogAspect : RESPONSE IS : This is getAllInfo() function
从而实现了AOP的操作日志功能
三、参考
1. https://blog.csdn.net/q982151756/article/details/80513340
2. https://www.bilibili.com/video/av72006931?p=2