使用SpringAOP实现公共字段填充

news2024/12/28 20:48:53

文章目录

    • 概要
    • 整体架构流程
    • 技术细节
    • 小结

概要

新增员工或者新增菜品分类时需要设置创建时间、创建人、修改时间、修改人等字段,在编辑员工或者编辑菜品分类时需要设置修改时间、修改人等字段。这些字段属于公共字段,也就是也就是在我们的系统中很多表中都会有这些字段,如下:

序号字段名含义数据类型
1create_time创建时间datetime
2create_user创建人idbigint
3update_time修改时间datetime
4update_user修改人idbigint

而针对于这些字段,我们的赋值方式为:

1). 在新增数据时, 将createTime、updateTime 设置为当前时间, createUser、updateUser设置为当前登录用户ID。

2). 在更新数据时, 将updateTime 设置为当前时间, updateUser设置为当前登录用户ID。

我们使用AOP切面编程,实现功能增强,来完成公共字段自动填充功能。

技术细节

在实现公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码。在上述的问题分析中,我们提到有四个公共字段,需要在新增/更新中进行赋值操作, 具体情况如下:

序号字段名含义数据类型操作类型
1create_time创建时间datetimeinsert
2create_user创建人idbigintinsert
3update_time修改时间datetimeinsert、update
4update_user修改人idbigintinsert、update

实现步骤:

1). 自定义注解 AutoFill,用于标识需要进行公共字段自动填充的方法

2). 自定义切面类 AutoFillAspect,统一拦截加入了 AutoFill 注解的方法,通过反射为公共字段赋值

3). 在 Mapper 的方法上加入 AutoFill 注解

若要实现上述步骤,需掌握以下知识(之前课程内容都学过)

技术点:枚举、注解、AOP、反射

  • 枚举类:
package com.sky.enumeration;

/**
 * 数据库操作类型
 */
public enum OperationType {

    /**
     * 更新操作
     */
    UPDATE,

    /**
     * 插入操作
     */
    INSERT

}
  • 自定义注解:
package com.sky.annotation;

import com.sky.enumeration.OperationType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解,用于标识某个方法需要进行功能字段自动填充处理
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
    //数据库操作类型:UPDATE INSERT
    OperationType value();
}
  •  自定义切面类:
  1. 公共字段填充,我们选择在连接点(方法)执行前就进行,所以用@Before
  2. 将连接点上的@AutoFill注解拦截下
  3. 利用注解的.value()获取到注解中的内容(数据库操作类型)
  4. 获取到该连接点的参数
  5. 准备好填充的内容
  6. 利用反射根据数据库操作类型进行填充
  • package com.sky.aspect;
    
    import com.sky.annotation.AutoFIll;
    import com.sky.constant.AutoFillConstant;
    import com.sky.context.BaseContext;
    import com.sky.enumeration.OperationType;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    import java.time.LocalDateTime;
    
    @Aspect
    @Slf4j
    @Component
    public class AutoFillAspect {
    
        //切入点
        @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFIll)")
        public void autoFillPointCut() {
        }
    
        //前置通知,在通知中进行公共字段的赋值
        @Before("autoFillPointCut()")
        public void autoFill(JoinPoint joinPoint) {
            log.info("进行公共字段赋值");
            //获取当前被拦截方法上的注解
            AutoFIll autoFIll = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(AutoFIll.class);
            //MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
            //AutoFIll autoFill = signature.getMethod().getAnnotation(AutoFIll.class);
            //获取数据库操作类型(INSERT,UPDATE)
            OperationType operationType = autoFIll.value();
            //获取当前被拦截方法上的参数(实体对象)
            Object[] args = joinPoint.getArgs();
            if (args == null || args.length == 0) {
                return;
            }
            Object entity = args[0];
            //准备要填充的内容
            LocalDateTime now = LocalDateTime.now();
            Long id = BaseContext.getCurrentId();
            //根据数据库操作类型进行赋值
            if (operationType == OperationType.INSERT) {
                try {
                    Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                    Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                    Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                    Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                    setCreateTime.invoke(entity, now);
                    setCreateUser.invoke(entity, id);
                    setUpdateTime.invoke(entity, now);
                    setUpdateUser.invoke(entity, id);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (operationType == operationType.UPDATE) {
                try {
                    Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                    Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                    setUpdateTime.invoke(entity, now);
                    setUpdateUser.invoke(entity, id);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    @AutoFIll(value = OperationType.INSERT)
        void insert(Dish dish);

效果展示

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

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

相关文章

Flux:Midjourney的新图像模型挑战者

--->更多内容&#xff0c;请移步“鲁班秘笈”&#xff01;&#xff01;<--- Black Forest Labs是一家由前Stability.ai开发人员创立的AI初创公司&#xff0c;旨在为图像和视频创建尖端的生成式 AI 模型。这家初创公司声称&#xff0c;其第一个模型系列Flux.1为文本到图像…

【FAQ】为啥MultipartFile 的InputStream available会为0

背景 在Spring boot 文件上传案例中可能会存在获取MultipartFile InputStream.available()方法为0的情况&#xff0c;导致在文件上传到Minio后对象大小为0的情况 问题原因 在介绍问题原因前我们先探究下MultipartFile 是怎么实现的 这里只是剖析InputStream&#xff0c;所以…

Linux驱动入门实验班day03-另一种注册cdev的方式

问题&#xff1a;原来的函数/*major register_chrdev(0, "100ask_hello", &hello_drv);*/会将主设备号major对应的所有次设备号&#xff0c;对应的设备节点&#xff0c;总是访问到驱动程序hello_drv。 这个问题&#xff0c;会导致主设备号不够用。 解决方式&am…

c++ - unordered_set与unordered_map模拟实现

文章目录 前言一、unordered_set模拟实现二、unordered_map模拟实现 前言 1、unordered_set与unordered_map的介绍与接口使用可参考&#xff1a;unordered_set 、 unordered_map。 2、unordered_set和 unordered_map 的底层实现都是基于哈希表的。哈希表是一种通过哈希函数组织…

HarmonyOS(48) 挂载卸载事件 UI组件的添加和删除监听

UI组件的添加和删除监听 一级目录示例代码参考资料 一级目录 我们通过if条件添加组件的时候&#xff0c;是可以通过onAttach、onDetach、onAppear、onDisAppear来监听组件的添加和删除。 示例代码 // xxx.ets// xxx.ets import { promptAction } from kit.ArkUIEntry Compo…

2024华数杯数学建模A题完整论文讲解(含每一问python代码+结果+可视化图)

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了2024 年华数杯全国大学生数学建模竞赛A题机器臂关节角路径的优化设计完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成…

VBA信息获取与处理:VBA代码分类及如何利用代码自动关闭空闲文件

《VBA信息获取与处理》教程(版权10178984)是我推出第六套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。这部教程给大家讲解的内容有&#xff1a;跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互…

LC65---2164.对奇偶下标分别排序(排序)--Java版

1.题目 2.思路 &#xff08;1&#xff09;分别提取奇数下标和偶数下标的元素。 &#xff08;2&#xff09;对奇数下标的元素按非递增顺序排序&#xff0c;对偶数下标的元素按非递减顺序排序。 (3)最后将排列好的数字进行合并。 补充&#xff1a; 3.代码实现 class Solution…

PyCharm 2024.1 总结和最新变化

​ 您好&#xff0c;我是程序员小羊&#xff01; 前言 PyCharm 2024.1 是 JetBrains 最新发布的Python集成开发环境&#xff08;IDE&#xff09;&#xff0c;旨在提供更强大的功能和更好的用户体验。以下是对这个版本的总结和最新变化的介绍 智能代码建议和自动完成&#xff1a…

C语言 ——— 学习并使用 strerror 函数

目录 学习strerror函数 使用strerror函数 学习strerror函数 库函数在执行的时候&#xff0c;发生了错误&#xff0c;会将这个错误码存放在errno这个变量中&#xff0c;而errno是C语言提供的一个全局变量 而strerror函数是一个错误报告函数&#xff0c;可以将对应的错误码转…

roomformer-端到端矢量检测模型

论文&#xff1a;Connecting the Dots: Floorplan Reconstruction Using Two-Level Queries 论文地址&#xff1a;https://arxiv.org/pdf/2211.15658 code&#xff1a;https://github.com/ywyue/RoomFormer or https://github.com/woodfrog/poly-diffuse 参考&#xff1a;ht…

指针的指针作为形参实测

1. VS2019里面创建C控制台工程 2. 代码 #include <iostream>uint8_t buf[3][10] { {1,2,3},{4,5,6,7,8},{9,0} }; uint8_t len1 3,len2 5,len3 2;void f1(uint8_t **dstBuf, uint8_t *dstLen) {*dstBuf buf[0];*dstLen len1; }void f2(uint8_t** dstBuf, uint8_t*…

密码学基础-数据加密

密码学基础-对称加密与非对称加密 概述 安全通常从四个方面来定义&#xff1a; 机密性完整性合法性&#xff08;可用性&#xff0c;合法的数据才可用&#xff09;不可否认性&#xff08;发送方不可否认发送过的消息&#xff0c;接收方不可否认接收过的消息&#xff09; 对当…

低代码: 开发难点分析,核心技术架构设计

开发难点分析 1 &#xff09;怎样实现组件 核心问题&#xff1a;编辑器 和 页面其实整个就是一系列元素构成的这些元素的自然应该抽象成组件&#xff0c;这些组件的属性应该怎样设计在不同的项目中怎样做到统一的使用 2 &#xff09;跨项目使用 在不同的项目中怎样做到统一的…

最强开源文生图模型一夜易主!SD一作、Stabililty AI核心成员Robin Rombach下场创业了,一出手就是王炸。

时隔4个月&#xff0c;开源文生图模型霸主Stable Diffusion原班人马再创业&#xff01;2024年8月1日官宣&#xff1a;Black Forest Labs成立&#xff0c;公司的第一个产品FLUX.1系列模型包含专业版、开发者版、快速版三种模型&#xff0c;效果直接秒杀Midjourney、DALL-E和Stab…

解决报错:AssertionError: Torch not compiled with CUDA enabled

首先查看自己的cuda是否可用 torch.cuda.is_available()这里我的cuda是不适配torch的&#xff0c;所以需要重新安装适配的torch 查看自己的cuda版本 方法1 方法2 在cmd处输入nvidia-smi 这样可以找到的自己的CUDA版本安装符合自己版本的pytorch 进入pytorch官网https://pyt…

双指针实现删除字符串中的所有相邻重复项

class Solution:def removeDuplicates(self, s: str) -> str:res list(s)slow fast 0length len(res)while fast < length:# 如果一样直接换&#xff0c;不一样会把后面的填在slow的位置res[slow] res[fast]# 如果发现和前一个一样&#xff0c;就退一格指针if slow …

app逆向实战:某监管app2.0.5版本ROOT检测绕过

本篇博客旨在记录学习过程&#xff0c;不可用于商用等其它途径 场景 如下图&#xff0c;在我们打开APP时页面提示如此样式说明被检测到ROOT了&#xff0c;这种情况下无法进入页面请求抓包。 查壳 如果这个APP没有加固&#xff0c;那我们可以通过反编译修改检测的代码或者F…

Django与数据库

目录 创建项目app 路由子表 数据库 创建数据库 什么是ORM 定义数据库表 Django Admin 管理数据 过滤条件 代码直接生成HTML 使用模板 前后端分离架构 对资源的增删改查处理 列出客户 添加客户 临时取消 CSRF 校验 修改客户信息 删除客户 Django中ORM的处理 数据模…

QThread::wait: Thread tried to wait on itself

调用QThread的wait()方法时&#xff0c;报警&#xff1a;QThread::wait: Thread tried to wait on itself 原因&#xff1a;在自己的线程中调用线程的wait()方法。 解决方法&#xff1a;在线程外的其他线程中&#xff0c;调用线程的wait()方法。 示例代码如下&#xff1a; …