一张思维导图带你学会SpringBoot使用AOP实现日志管理功能

🧑‍💻作者名称:DaenCode
🎤作者简介:啥技术都喜欢捣鼓捣鼓,喜欢分享技术、经验、生活。
😎人生感悟:尝尽人生百味,方知世间冷暖。
📖所属专栏:SpringBoot实战


系列文章目录

标题
一文带你学会使用SpringBoot+Avue实现短信通知功能(含重要文件代码)
一张思维导图带你学会Springboot创建全局异常、自定义异常
一张思维导图带你打通SpringBoot自定义拦截器的思路
28个SpringBoot项目中常用注解,日常开发、求职面试不再懵圈
一张思维导图带你学会SpringBoot、Vue前后端分离项目线上部署
一张思维导图带你学会使用SpringBoot中的Schedule定时发送邮件
一张思维导图带你学会使用SpringBoot异步任务实现下单校验库存

在这里插入图片描述


思维导图

在这里插入图片描述

🌟AOP介绍

基本概念:在不改变原有功能的逻辑,增加新的功能。
应用场景

  • 权限控制
  • 日志处理
  • 事务控制

下面以对产品数据增删改查功能,进行日志管理功能为例,对AOP中的核心概念作出介绍,请参考下表

概念解析对应日志管理功能
核心关注点业务逻辑的主要功能,应用程序主要关注的部分产品数据的增删改查
横切关注点与核心关注点相关但不属于核心关注点的功能,在系统的多个模块或组件中散布记录产品操作的日志
通知在特定切入点执行时要执行的代码,实现横切关注点的具体逻辑。可以在目标方法执行之前、之后或抛出异常时执行执行记录日志的代码
连接点可以插入通知的特定点,通常是方法执行的位置产品表操作的方法
切入点通过表达式或规则定义的连接点的集合。确定了哪些连接点与通知关联起来选择所有的插入、更新或删除操作的连接点集合
切面横切关注点和通知的组合,将通知应用到切入点匹配的连接点上包含记录日志的通知和定义切入点的规则
目标被通知的对象或类,即应用程序中执行具体操作的对象或方法对产品数据作出操作的对象或方法
织入将切面应用到目标对象上,创建新的代理对象的过程。可以在编译时、加载时或运行时进行将日志管理切面应用到产品表操作的目标对象上,以记录日志

🌟具体实现步骤

数据准备

创建产品表、以及日志表,并向产品表添加相关数据。

CREATE TABLE `product`  (
  `id` int(11) NOT NULL,
  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `price` decimal(10, 2) NULL DEFAULT NULL,
  `stock` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
-- ----------------------------
-- Records of product
-- ----------------------------
INSERT INTO `product` VALUES (1, '苹果13', 10.99, 50);
INSERT INTO `product` VALUES (2, '小米10', 19.99, 99);
INSERT INTO `product` VALUES (3, '华为mate20', 5.99, 19);

CREATE TABLE `log`  (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `operation` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `data` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `operate_time` datetime NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

引入相关依赖

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

创建实体类

Product类

public class Product implements Serializable {
    private Integer id;
    private String name;
    private BigDecimal price;
    private Integer stock;
}

Log类

public class Log implements Serializable {
    private Integer id;
    private String operation;
    private String data;
    private Timestamp operateTime;
}

自定义注解@LogTip

自定义注解,用于标记记录日志的方法。

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogTip {

    String value() default "";

}

定义切面类

切面类由切点PointCut+通知Advice共同构成。有关于通知的类型以及解释,可以查看思维导图中的通知节点。有关于JoinPoint的API见下表

API描述
getSignature()获取连接点的签名,返回一个MethodSignature对象
getArgs()获取连接点方法的参数数组
getTarget()获取目标对象
getThis()获取当前代理对象
toShortString()生成连接点的简短描述
toLongString()生成连接点的详细描述
getStaticPart()获取静态连接点部分
getKind()获取连接点的类型
getSourceLocation()获取连接点所在位置的源代码位置
@Component
@Aspect
public class LogAspect {
    @Autowired
    private LogMapper logMapper;
    @Pointcut("@annotation(com.shoanjen.redis.annotation.LogTip)")
    public void pointCut(){}

    @AfterReturning("pointCut()")
    public void getLogInfo(JoinPoint point) throws Throwable {
        // 获取方法参数列表
        Object[] args = point.getArgs();
        //获取自定义注解上的描述信息
        MethodSignature methodSignature= (MethodSignature) point.getSignature();
        Method method=methodSignature.getMethod();
        LogTip annotation=method.getAnnotation(LogTip.class);
        String desc=annotation.value();
        // 获取操作的数据
        String data = Arrays.toString(args);
        // 记录日志
        saveLog(desc, data);
    }
    private void saveLog(String desc, String data) {
        Log log = new Log();
        log.setOperation(desc);
        log.setData(data);
        log.setOperateTime(new Timestamp(System.currentTimeMillis()));
        logMapper.save(log);
    }
}

LogMapper

public interface LogMapper {
    void save(Log log);
}
<insert id="save" parameterType="com.shoanjen.redis.model.Log" keyColumn="id" keyProperty="id" useGeneratedKeys="true">
       INSERT INTO log(operation, data, operate_time) VALUES (#{operation}, #{data}, #{operateTime});
</insert>

ProductController

这里以上一篇文章一张思维导图带你学会使用SpringBoot异步任务实现下单校验库存中的产品下单功能为例子,对其记录日志。

@RestController
@RequestMapping("/api/v1/product")
public class ProductController {
    @Autowired
    private ProductService productService;

    @Autowired
    private ValidateTask validateTask;
    @LogTip("产品下单")
    @RequestMapping("order")
    public JsonData order(@RequestParam int productId,@RequestParam int quantity) throws ExecutionException, InterruptedException {
        Future<Boolean> validateResult=validateTask.validateStock(productId,quantity);
        System.out.println(validateResult.get());
        Boolean flag=false;
        //判断异步任务是否完成
        if (validateResult.isDone()){
            try {
                flag=validateResult.get();
            } catch (Exception e) {
                flag=false;
            }

        }
        if (flag){
            return JsonData.buildSuccess("下单成功");
        }else {
            return JsonData.buildError("下单失败,库存不足");
        }
    }
}

🌟最终测试

接口请求测试

在这里插入图片描述
在这里插入图片描述

日志表查看

在这里插入图片描述

🌟写在最后

有关于SpringBoot使用AOP实现日志管理功能到此就结束了。感谢大家的阅读,希望大家在评论区对此部分内容散发讨论,便于学到更多的知识。


请添加图片描述

  • 30
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 55
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DaenCode

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值