Spring AOP + 自定义注解 实现公共字段的填充

Spring AOP + 自定义注解 实现公共字段的填充

在这里插入图片描述

代码冗,不利于后期维护.

定义操作这些字段的方法类型

在这里插入图片描述

实现步骤:

  • 自定义注解AutoFill,用于表示操作这些公共字段的方法
  • 自定义切面类AutoFillAspect,统一拦截,通过反射获取方法入参,并填充公共字段
  • 在Mapper的insert、update的方法上加上自定义的AutoFill注解

代码:

- 不使用mybatis-plus自带的填充注解

必要依赖

 <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.7</version>
</dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.1.0</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.7.5</version>
</dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.18</version>
</dependency>

1、自定义注解AutoFill,用于表示操作这些公共字段的方法

import com.cwh.mpdemo.enums.OpreaType;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 {/*** 操作类型** @return*/OpreaType value() default OpreaType.INSERT;
}

2、自定义切面类AutoFillAspect,统一拦截,通过反射获取方法入参,并填充公共字段


import com.cwh.mpdemo.annotation.AutoFill;
import com.cwh.mpdemo.enums.OpreaType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
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.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;/*** @Aspect 标注为切面类*/
@Aspect
@Component
@Slf4j
public class AutoFillaspect {// 定义切点@Pointcut("execution(* com.cwh.mpdemo.mapper.*.*(..)) && @annotation(com.cwh.mpdemo.annotation.AutoFill)")public void pointcut(){}// 定义通知@Before("pointcut()")public void before(JoinPoint joinPoint){log.info("auto fill start...");MethodSignature signature = (MethodSignature) joinPoint.getSignature();AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);OpreaType value = annotation.value();//获取签名方法的入参Object[] args = joinPoint.getArgs();if (args.length ==0 ||args == null)  {return;}Object arg = args[0];try {// 填充字段if (value == OpreaType.INSERT){//通过反射给入参对象的字段赋值arg.getClass().getDeclaredMethod("setCreateTime", Date.class).invoke(arg, Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)));//实际中从ThreadLocal获取用户id          arg.getClass().getDeclaredMethod("setCreateUser",String.class).invoke(arg,"test");} arg.getClass(). getDeclaredMethod("setUpdateTime",Date.class).invoke(arg,Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)));//实际中从ThreadLocal获取用户idarg.getClass().getDeclaredMethod("setUpdateUser",String.class).invoke(arg,"test");}catch (Exception exception){log.error("auto fill error:{}",exception.getMessage());}log.info("auto fill end...");}
}
public enum OpreaType {INSERT,UPDATE;
}

3、在Mapper的insert、update的方法上加上自定义的AutoFill注解

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cwh.mpdemo.annotation.AutoFill;
import com.cwh.mpdemo.domain.SessionDomain;public interface SessionLoginMapper extends BaseMapper<SessionDomain> {@AutoFillvoid insertData(SessionDomain sessionDomain);
}

- 使用mybatis-plus自带的填充注解

首先在实体对象上加自动填充属性注解fill = FieldFill.INSERT

@Data
@TableName("session_login")
public class SessionDomain {@TableId(value = "id", type = IdType.AUTO)private Long id;@TableFieldprivate String userName;@TableField(fill = FieldFill.INSERT)private Date createTime;@TableField(fill = FieldFill.INSERT)private String createUser;@TableField(fill = FieldFill.UPDATE)private Date updateTime;@TableField(fill = FieldFill.UPDATE)private String updateUser;
}

实现元数据对象处理器接口MetaObjectHandler,实现insertFill,updateFill逻辑

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;@Component
public class AutoFillHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {// 设置属性值this.setFieldValByName("createTime", Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)), metaObject);this.setFieldValByName("updateTime", Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)), metaObject);//实际中从ThreadLocal获取用户idthis.setFieldValByName("createUser", "1", metaObject);this.setFieldValByName("updateUser", "1", metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {//实际中从ThreadLocal获取用户idthis.setFieldValByName("updateTime", Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)), metaObject);this.setFieldValByName("updateUser", "1", metaObject);}
}	

剩下就是在service层使用mapper接口insert、update数据即可。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python程序设计 多重循环(二)

1.打印数字图形 输入n&#xff08;n<9)&#xff0c;输出由数字组成的直角三角图形。例如&#xff0c;输入5&#xff0c;输出图形如下 nint(input("")) #开始 for i in range(1,n1):for j in range(1,i1):print(j,end"")print()#结束 2.打印字符图形 …

VSCode好用插件

由于现在还是使用vue2&#xff0c;所以本文只记录vue2开发中好用的插件。 美化类插件不介绍了&#xff0c;那些貌似对生产力起不到什么大的帮助&#xff0c;纯粹的“唯心主义”罢了&#xff0c;但是如果你有兴趣的话可以查看上一篇博客&#xff1a;VSCode美化 1. vuter 简介&…

数据结构——红黑树详解

一、红黑树的定义 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长出两倍&#xff0c…

Nginx反向代理和缓存

一、Nginx反向代理 1.调度和代理的区别&#xff1a; 1.调度基于内核层面&#xff0c;代理基于应用层面 2.代理必须实现一手托两家 3.调度不需要监听任何端口&#xff0c;不需要工作任何应用程序&#xff0c;代理需要工作和上游服务器一模一样的进程 4.调度没有并发上限&am…

C++的并发世界(三)——线程对象生命周期

0.案例代码 先看下面一个例子&#xff1a; #include <iostream> #include <thread>void ThreadMain() {std::cout << "begin sub thread:" << std::this_thread::get_id()<<std::endl;for (int i 0; i < 10; i){std::cout <&…

介绍一下Java的数据类型

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a;每天一个知识点 ✨特色专栏&#xff1a…

[RK3399-Android10] 关于USB触摸屏休眠状态无法唤醒设备的一种情况

问题描述 RK3399 Android10平台上&#xff0c;USB触摸屏在系统按键休眠之后&#xff0c;无法触摸唤醒设备。查看内核日志&#xff0c;发现休眠之后&#xff0c;USB设备直接断开&#xff0c;lsusb发现不了设备。休眠之后host接口没有断开电源&#xff0c;使用USB鼠标插在同一个…

【详细介绍WebKit的结构】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

PAC下的ROP问题

Armv8.3-A引入了pointer authentication选项。 pointer authentication可以减轻ROP攻击。 为了防止ROP攻击&#xff0c;在函数开始时&#xff0c;LR寄存器中的返回地址被签名。这意味着在寄存器的高位添加了一个PAC。在返回之前&#xff0c;使用PAC对返回地址进行验证。如果检查…

如何搭建一个个人网站,个人博客?

搭建一个个人网站可以是一个有趣且有益的过程。下面是一些基本步骤和考虑因素&#xff0c;帮助你开始这个过程&#xff1a; 一、确定目标和内容 网站类型&#xff1a;首先&#xff0c;你需要明确你的网站类型。是个人博客、作品集展示、在线商店还是其他类型&#xff1f;内容…

大学html作业-个人简历静态网站(免费)

大学html作业-个人简历静态网站&#xff08;免费&#xff09; 源码来自githab&#xff0c;有些简单的问题我都修复了。大家可以直接去找原作者的源码&#xff0c;如果githab打不开就从我下载的网盘里下载吧。 效果

SpringBoot中操作Bean的生命周期的方法

引言 在 Spring Boot 应用中&#xff0c;管理和操作 Bean 的生命周期是一项关键的任务。这不仅涉及到如何创建和销毁 Bean&#xff0c;还包括如何在应用的生命周期中对 Bean 进行精细控制。Spring 框架提供了多种机制来管理 Bean 的生命周期&#xff0c;这些机制使得开发者可以…