Spring:AOP概念和实现实例

一、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


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值