Spring中Aop实现日志功能

news2025/1/24 14:44:16

文章目录

  • 前言
  • 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.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.9.7</version>
      </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 测试删除

delete
新增和修改就不测试,同样的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/632260.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQL注入总结

Sql注入定义&#xff1a; 就是通过把sql命令插入到web表单提交或输入域名或页面请求的查询字符串&#xff0c;最终达到欺骗服务器执行的sql命令的目的。 sql注入分类&#xff1a; 基于联合查询 基于错误回显 基于盲注&#xff0c;分时间盲注和布尔型的盲注 基于user-agen…

NIN(Network In Network)

目录 论文信息摘要批注 主要工作1. MLPCONV结构1.1为什么11卷积层可以代替MLP层1.2 批注2. Global Average Pooling(GAP)3、NIN网络结构NIN论文解读及个人理解NIN网络的代码实现&#xff08;pytorch&#xff09; 参考文献 论文信息 论文名称&#xff1a;Network In Network 论…

SQL注入—报错注入

0x00 背景 SQL注入长期位于OWASP TOP10 榜首&#xff0c;对Web 安全有着很大的影响&#xff0c;黑客们往往在注入过程中根据错误回显进行判断&#xff0c;但是现在非常多的Web程序没有正常的错误回显&#xff0c;这样就需要我们利用报错注入的方式来进行SQL注入了。这篇文章会讲…

SpringBoot集成WebSocket的两种方式

本站在2014年4月时曾全面的学习HTML5的技术&#xff0c;特写过HTML5的WebSocket示例&#xff0c;当时使用的Servlet3.0规范中的API&#xff0c;需要Tomcat7的支持&#xff08;貌似在Tomcat6的后期维护版本也增加了WebSocket的支持&#xff09;&#xff0c;早在当初该示例还是本…

SVN注册下载安装以及使用一气呵成

本博客根据SVNbucket官方视频学习制作的,这里记录本人操作的记录 视频链接: https://www.bilibili.com/video/BV1k4411m7mP?vd_sourcea4c65e14d1ff11ea858cadc164fbb59e 一 .SVN的介绍 1.SVN是什么 查阅资料可以知道 ,这是一个开放源代码的版本控制系统,管理着随时间改变的…

docsify项目部署(华为云+宝塔+centos+docker+nginx)踩坑指南

docsify部署&#xff08;华为云宝塔centosdockernginx&#xff09; &#x1f5e1;1、安装docker 首先在服务器中安装docker sudo yum install -y yum-utils由于之前我的python默认版本升级到了python3&#xff0c;但yum执行使用的是python2&#xff0c;就遇到报错 File &quo…

Hbase架构

HBase 系统遵循 Master/Salve 架构&#xff0c;由三种不同类型的组件组成&#xff1a; client 提供了访问hbase的接口提供cache缓存提高访问hbase的效率 , 比如region的信息 Zookeeper保证任何时候&#xff0c;集群中只有一个 Master&#xff1b;存储所有 Region 的寻址入口&…

基于深度学习的高精度工人阶梯检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度工人阶梯检测识别系统可用于日常生活中或野外来检测与定位工人阶梯目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的工人阶梯目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5…

Verilog基础:标识符的层次名引用

相关文章 Verilog基础&#xff1a;表达式位宽的确定&#xff08;位宽拓展&#xff09; Verilog基础&#xff1a;表达式符号的确定 Verilog基础&#xff1a;数据类型 Verilog基础&#xff1a;位宽拓展和有符号数运算的联系 Verilog基础&#xff1a;case、casex、ca…

Java8 Stream详解及创建流方法使用示例(二)

本章介绍Stream 创建流的操作&#xff1a;创建流指的是将一个集合或其他数据源转换为 Stream 流对象的过程。通常情况下&#xff0c;我们可以使用 Stream 类的静态方法来创建流对象&#xff0c;如 Stream.of()、Collections.stream() 等。这些方法将返回一个 Stream 流对象&…

【模块三:职业成长】35|模块导读:回过头来看,你觉得架构师到底是做什么的?

你好&#xff0c;我是郭东白。我们今天就正式进入模块三的学习了。 我们在开篇词里面介绍了&#xff0c;模块三的目的是向你介绍架构师的能力维度&#xff0c;以及获取这些能力的方法。既然是总结架构师成长的课程&#xff0c;那么“什么是架构师”就是一个绕不过去的话题。 …

操作系统-内存管理-虚拟内存管理

目录 一、虚拟内存定义和特征 二、请求分页管理 页表机制 缺页中断机构 地址变换机构 三、页面置换算法 3.1最佳置换算法(OPT) 3.2先进先出置换算法(FIFO) 3.3最近最久未使用置换算法(LRU) 3.4时钟置换算法(CLOCK) 3.4.1简单时钟置换算法 3.4.2改进型时钟置换算法 四、…

数据库—mysql、数据库编程(API)

1. Linux平台准备 &#xff08;1&#xff09;安装SDK开发包的命令 sudo apt-get install libmysqlclient-dev &#xff08;2&#xff09;编译时需要链接的库:-lmysqlclient 2. mysql 的初始化和清理 #include <mysql/mysql.h> MYSQL mysql1; //创建句柄 mysql_init(&…

springboot+java高校图书馆图书借阅挂失崔还系统

功本次设计任务是要设计一个图书借阅系统&#xff0c;通过这个系统能够满足图书借阅系统的管理及用户的图书借阅功能。系统的主要功能包括&#xff1a;主页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;借阅证件管理&#xff0c;挂失信息管理&#xff0c;图书信息管理…

华为OD机试真题 JavaScript 实现【快速寻找某字符】【牛客练习题】

一、题目描述 给定一个一个目标值 target和一个 元素升序的无重复数字字符串 &#xff0c;写一个函数搜索 字符串 中的 target&#xff0c;如果目标值存在返回下标&#xff08;下标从 0 开始&#xff09;&#xff0c;否则返回 -1。 二、输入描述 第一行输入一个目标值target…

pullup和pulldown在verilog中的使用方法

0 前言 这段时间涉及到了IO-PAD&#xff0c;在IO-PAD的RTL的时候注意到了pullup和pulldown&#xff0c;对这个知识比较好奇&#xff0c;就研究了一下&#xff0c;顺便记录下来&#xff0c;IO-PAD的内容等我再研究研究再考虑记录吧 >_< 1 pullup和pulldown的介绍 pullu…

springboot3错误处理机制源码分析

ErrorMvcAutoConfiguration 在springboot启动时会自动装配默认的错误处理机制 ErrorMvcAutoConfiguration springboot正在运行&#xff0c;此时发生了404的错误。&#xff08;业务错误场景&#xff09;分析底层处理流程。 1.如果在对应的controller层中设置了对应的错误处理器…

【裸机开发】链接脚本(.lds文件)的基本语法

目录 一、什么是链接脚本&#xff1f; 二、链接脚本的基本语法格式 1、常用命令 2、内置变量 三、链接脚本的简单案例 一、什么是链接脚本&#xff1f; 一段程序的编译需要经历四个阶段&#xff08;预处理—编译—汇编—链接&#xff09;&#xff0c;而链接脚本管理的就是…

专业实习报告范本4篇

专业实习报告范本1 一、实习起止日期&#xff1a; 二、实习单位及部门&#xff08;岗位&#xff09;&#xff1a; 三、主要实习内容&#xff1a; 对基础知识和专业理论知识的掌握及运用情况&#xff1a; 通过两年半的学习和两个月的紧张培训&#xff0c;让我学会了电路图的分析…

彻底关闭 Win10 系统自动更新【四大步骤】

Windows 10 的自动更新非常顽固&#xff0c;多用户在网上试了各种关闭win10自动更新的方法&#xff0c;刚开始看着好像是关闭更新了&#xff0c;可没过多久系统就又开始自动更新了。今天笔者就来教大家如何彻底关闭win10自动更新&#xff0c;该方法亲测有效。 一、禁用 Window…