Spring中Aop实现日志功能

文章目录

  • 前言
  • 1.环境搭建
  • 2.设计日志记录表
  • 3.aop需要引入aspectj依赖
  • 4.日志实体类设计
  • 5.自定义日志BusiLog注解
  • 6.定义日志切面
    • 6.1 此处只使用了环绕通知
    • 6.2 @Aspect中有5种通知
  • 7.业务中使用注解
  • 8.测试
    • 8.1 测试查询
    • 8.2 测试删除

前言

上篇分享了jdk动态代理以及cglib代理,是对某个接口或者类进行增强扩展实现。AOP (Aspect Orient Programming),面向切面编程,AOP可以拦截指定的方法并且对方法增强,而且无需侵入到业务代码中,使业务与非业务处理逻辑分离,实现开闭原则。下边我们以实现aop实现日志的记录为例。

1.环境搭建

jdk1.8+IDEA+MyBatisPlus+mysql实现。
具体的安装不在这里赘述。

2.设计日志记录表

CREATE TABLE `busi_log` (
  `ID` bigint(20) NOT NULL COMMENT '主键id',
  `USER_ID` bigint(20) DEFAULT NULL COMMENT '用户id',
  `CLASS_NAME` varchar(255) DEFAULT NULL COMMENT '类名称',
  `METHOD` varchar(100) DEFAULT NULL COMMENT '方法名称',
  `DESCRIPTION` text COMMENT '方法描述',
  `CREATE_DATE` datetime DEFAULT NULL COMMENT '创建日期',
  PRIMARY KEY (`ID`) USING BTREE,
  KEY `ID` (`ID`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='操作日志表';

3.aop需要引入aspectj依赖

      <dependency>
          <groupId>org.aspectjgroupId>
          <artifactId>aspectjweaverartifactId>
          <version>1.9.7version>
      dependency>

4.日志实体类设计

/**
 * 操作日志表
 */
@TableName("busi_log")
public class BusiLog {
    //主键id
    @TableId(value = "ID", type = IdType.ASSIGN_ID)
    protected Long id;

    //用户id
    @TableField(value = "USER_ID")
    protected Long userId;

    //类名称
    @TableField(value = "CLASS_NAME")
    protected String className;

    //方法名称
    @TableField(value = "METHOD")
    protected String method;

    //方法描述
    @TableField(value = "DESCRIPTION")
    protected String description;

    // 创建日期
    @TableField(value = "CREATE_DATE", fill = FieldFill.INSERT)
    protected Date createDate;
    //此处省略 set get方法
}

5.自定义日志BusiLog注解

/**
 * 自定义日志注解
 */
import java.lang.annotation.*;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface BusiLog {

    /**
     * 操作具体某个功能的描述
     * @return
     */
    String desc() default "";
}

6.定义日志切面

6.1 此处只使用了环绕通知

实际业务中我们还可能记录异常日志,操作日志,等等。

/**
 * 日志切面类
 */
@Component
@Aspect
@Slf4j
public class BusiLogAop {

    /**
     * 引入日志持久化的mapper类
     */
    @Autowired
    private BusiLogMapper busiLogMapper;

    /**
     * 定义BusLogAop的切入点为标记@BusLog注解的方法
     */
    @Pointcut(value = "@annotation(com.elite.mybatisplus.annotation.BusiLog)")
    public void pointcut() {
    }

    /**
     * 业务操作环绕通知
     *
     * @param proceedingJoinPoint
     * @retur
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) {
        log.info("==========BusiLogAop环绕通知===============");
        //执行目标方法
        Object result = null;
        try {
            result = proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        //目标方法执行完成后,获取目标类、目标方法上的业务日志注解上的功能名称和功能描述
        Object target = proceedingJoinPoint.getTarget();
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        BusiLog anno = signature.getMethod().getAnnotation(BusiLog.class);
        //没设计好名字,注解和实体类名字一致了
        com.elite.mybatisplus.entity.BusiLog busiLogEntity = new com.elite.mybatisplus.entity.BusiLog();
        busiLogEntity.setUserId(1L); //此处写死
        busiLogEntity.setClassName(target.getClass().getName());
        busiLogEntity.setMethod(signature.getMethod().getName());
        busiLogEntity.setDescription(anno.desc());
        busiLogEntity.setCreateDate(new Date());
        //保存业务操作日志信息
        this.busiLogMapper.insert(busiLogEntity);
        log.info("----BusAop 环绕通知 end");
        return result;
    }
}

6.2 @Aspect中有5种通知

  • @Before:前置通知, 在方法执行之前执行
  • @Aroud:环绕通知, 围绕着方法执行
  • @After:后置通知, 在方法执行之后执行
  • @AfterReturning:返回通知, 在方法返回结果之后执行
  • @AfterThrowing:异常通知, 在方法抛出异常之后

7.业务中使用注解

直接在方法上边使用注解即可。

/**
 * 人员信息管理
 */
@RestController
public class PersonController {

    @Autowired
    IPersonService personService;

    /**
     * 查询人员信息列表
     * @return
     */
    @BusiLog(desc = "查询人员信息列表")
    @GetMapping("/getPersonList")
    public List<Person> getPersonList(){
        return  personService.list();
    }

    /**
     * 新增人员信息
     */
    @BusiLog(desc = "新增人员信息")
    @PostMapping("/addPerson")
    public String addPerson(@RequestBody Person person){
        personService.save(person);
        return "新增人员信息成功!";
    }

    /**
     * 更新人员信息
     */
    @BusiLog(desc = "更新人员信息")
    @PostMapping("/updatePerson")
    public String updatePerson(@RequestBody Person person){
        personService.updateById(person);
        return "更新人员信息成功!";
    }
    /**
     * 删除人员信息
     */
    @BusiLog(desc = "删除人员信息")
    @GetMapping("/deletePersonById/{id}")
    public String deletePersonById(@PathVariable("id")Long id){
       personService.removeById(id);
       return "删除成功!";
    }
}

8.测试

此处我们只测试查询,看看效果。

8.1 测试查询

查询

8.2 测试删除

Spring中Aop实现日志功能_第1张图片
新增和修改就不测试,同样的方法。

你可能感兴趣的:(springboot,Java,spring,java,后端)