spring AOP实现日志管理

前言

spring AOP是使用spring提供的切面来横向拓展项目,使得一些和主业务无关的操作尽可能实现解耦,比如说我们经常使用的日志。

注: 需要用到pom文件

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

实操

1、编写一个自定义的注解@MyLog
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public  @interface MyLog {
    /** 操作类型 **/
    String type();
    /** 操作解释 **/
    String msg();
}
2、entity实体类(日志操作的实体)
package com.example.demo001.entity;

import java.io.Serializable;
import java.util.Date;

public class Mylog implements Serializable {

    private Long id;

    private String type;

    private String msg;

    private Date time;

    private String args;

    public Mylog() {
    }

    public Mylog(Long id, String type, String msg, Date time,String args) {
        this.id = id;
        this.type = type;
        this.msg = msg;
        this.time = time;
        this.args = args;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Date getTime() {
        return time;
    }

    public void setTime(Date time) {
        this.time = time;
    }

    public String getArgs() {
        return args;
    }

    public void setArgs(String args) {
        this.args = args;
    }
}

3、mapper层(插入日志)
@Mapper
public interface MylogMapper {

    @Insert("insert into mylog (type,msg,time,args) values (#{type},#{msg},#{time},#{args})")
    int insert(Mylog mylog);
}
4、切面类

//声明这是一个组件
@Component
//声明这是一个切面Bean
@Aspect
public class TestAspect {


    @Autowired
    private MylogMapper mapper;

    /**
     * 设置操作日志切入点 记录操作日志 在注解的位置切入代码
     */
    @Pointcut("@annotation(com.example.demo001.aop.MyLog)")
    public void aspect(){   }

    //最终通知
    //returning能够将目标方法的返回值传到切面增强方法里
    //声明rvt时指定的类型会限制目标方法必须返回指定类型(String)的值或没有返回值
    //此处将rvt的类型声明为Object,意味着对目标方法的返回值不加限制
    @AfterReturning(pointcut ="aspect()",returning = "rvt")
    public void AfterReturning(String rvt){
    }

    //异常通知
    //声明e时指定的类型会限制目标方法必须抛出指定类型的异常
    //此处将e的类型声明为Throwable,意味着对目标方法抛出的异常不加限制
    @AfterThrowing(pointcut="aspect()",throwing="e")
    public void AfterThrowing(Throwable e){
        System.out.println("--------AfterThrowing方法开始执行:"+e);
    }

    public Map<String, String> converMap(Map<String, String[]> paramMap) {
        Map<String, String> rtnMap = new HashMap<String, String>();
        for (String key : paramMap.keySet()) {
            rtnMap.put(key, paramMap.get(key)[0]);
        }
        return rtnMap;
    }


    //@Around注解可以用来在调用一个具体方法前和调用后来完成一些具体的任务。
    //功能很强大,可以深入了解下
    @Around("aspect()")
    public Object Around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("--------Around方法开始执行");

        Mylog mylog = new Mylog();

        //获取自定义注解里面的值
        Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
        MyLog myLog = method.getAnnotation(MyLog.class);
        String type = myLog.type();
        String msg = myLog.msg();


        /*String className = joinPoint.getTarget().getClass().getName();
        String name = method.getName();*/


        Object[] objs = joinPoint.getArgs();
        String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); // 参数名
        Map<String, Object> args = new HashMap<String, Object>();
        for (int i = 0; i < objs.length; i++) {
            args.put(argNames[i], objs[i]);
        }
        System.err.println("入参:"+ args);

       /*执行日志入库的操作*/
        mylog.setType(type);
        mylog.setMsg(msg);
        mylog.setArgs(args.toString());
        mylog.setTime(new Date());
        mapper.insert(mylog);

        Object result =joinPoint.proceed();
        return result;

    }

}

5、controller类
package com.example.demo001.controller;

import com.example.demo001.aop.MyLog;
import com.example.demo001.entity.User;
import com.example.demo001.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


@RestController
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @MyLog(type = "查询", msg = "用户列表查询")  //这里使用的自定义注解
    @RequestMapping("users")
    public List<User> users(Long id, String name ) {
        System.out.println("------"+id+"------"+name+"------");
        return userMapper.select();
    }
}


测试

这里查询的是用户列表,然后经过切面,获取操作参数入库。
在这里插入图片描述
数据库中已经获取了切面的信息了,大功告成,这里还能获取一些类信息,方法信息,你也可以把操作人等信息也存储起来,增删改查的操作也都是如此。
在这里插入图片描述

  • 0
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值