spring中注解autofill公共字段自动填充的方法

[复制链接]
admin 发表于 2025-9-15 13:35:13 | 显示全部楼层 |阅读模式
spring中注解autofill公共字段自动填充的方法
枚举、注解、AOP、反射
| **序号** | **字段名**  | **含义** | **数据类型** |
| -------- | ----------- | -------- | ------------ |
| 1        | create_time | 创建时间 | datetime     |
| 2        | create_user | 创建人id | bigint       |
| 3        | update_time | 修改时间 | datetime     |
| 4        | update_user | 修改人id | bigint       |

**实现步骤:**

1). 自定义注解 AutoFill,用于标识需要进行公共字段自动填充的方法
1,代码:
  1. package com.sky.annotation;

  2. import com.sky.enumeration.OperationType;

  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;

  7. /**
  8. * 自定义注解,用于标识某个方法需要进行功能字段自动填充处理
  9. */
  10. @Target(ElementType.METHOD) // 注解作用在方法上
  11. @Retention(RetentionPolicy.RUNTIME) // 注解保留在运行时
  12. public @interface AutoFill {
  13.     //数据库操作类型:UPDATE INSERT
  14.     OperationType value();
  15. }
复制代码
1.jpg

其中OperationType已在sky-common模块中定义枚举类
代码如下:
  1. package com.sky.enumeration;

  2. /**
  3. * 数据库操作类型
  4. */
  5. public enum OperationType {

  6.     /**
  7.      * 更新操作
  8.      */
  9.     UPDATE,

  10.     /**
  11.      * 插入操作
  12.      */
  13.     INSERT

  14. }
复制代码
2.jpg

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

**自定义切面 AutoFillAspect**

在sky-server模块,创建com.sky.aspect包。
代码如下:

  1. package com.sky.aspect;

  2. import com.sky.annotation.AutoFill;
  3. import com.sky.constant.AutoFillConstant;
  4. import com.sky.context.BaseContext;
  5. import com.sky.enumeration.OperationType;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.aspectj.lang.JoinPoint;
  8. import org.aspectj.lang.annotation.Aspect;
  9. import org.aspectj.lang.annotation.Before;
  10. import org.aspectj.lang.annotation.Pointcut;
  11. import org.springframework.stereotype.Component;
  12. import org.aspectj.lang.reflect.MethodSignature;
  13. import java.lang.reflect.Method;
  14. import java.time.LocalDateTime;

  15. /**
  16. * 自定义切面,实现公共字段自动填充处理逻辑
  17. */
  18. @Aspect
  19. @Component
  20. @Slf4j
  21. public class AutoFillAspect {
  22.     /**
  23.      * 切入点
  24.      */
  25.     @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
  26.     public void autoFillPointCut(){}
  27.     /**
  28.      * 前置通知,在通知中进行公共字段的赋值
  29.      */
  30.     @Before("autoFillPointCut()")
  31.     public void autoFill(JoinPoint joinPoint){
  32.         log.info("开始进行公共字段自动填充...");

  33.         //获取到当前被拦截的方法上的数据库操作类型
  34.         MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
  35.         AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象
  36.         OperationType operationType = autoFill.value();//获得数据库操作类型

  37.         //获取到当前被拦截的方法的参数--实体对象
  38.         Object[] args = joinPoint.getArgs();
  39.         if(args == null || args.length == 0){
  40.             return;
  41.         }

  42.         Object entity = args[0];

  43.         //准备赋值的数据
  44.         LocalDateTime now = LocalDateTime.now();
  45.         Long currentId = BaseContext.getCurrentId();

  46.         //根据当前不同的操作类型,为对应的属性通过反射来赋值
  47.         if(operationType == OperationType.INSERT){
  48.             //为4个公共字段赋值
  49.             try {
  50.                 Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
  51.                 Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
  52.                 Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
  53.                 Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

  54.                 //通过反射为对象属性赋值
  55.                 setCreateTime.invoke(entity,now);
  56.                 setCreateUser.invoke(entity,currentId);
  57.                 setUpdateTime.invoke(entity,now);
  58.                 setUpdateUser.invoke(entity,currentId);
  59.             } catch (Exception e) {
  60.                 e.printStackTrace();
  61.             }
  62.         }else if(operationType == OperationType.UPDATE){
  63.             //为2个公共字段赋值
  64.             try {
  65.                 Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
  66.                 Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

  67.                 //通过反射为对象属性赋值
  68.                 setUpdateTime.invoke(entity,now);
  69.                 setUpdateUser.invoke(entity,currentId);
  70.             } catch (Exception e) {
  71.                 e.printStackTrace();
  72.             }
  73.         }
  74.     }
  75. }
复制代码
3.jpg

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

以**CategoryMapper**为例,分别在新增和修改方法添加@AutoFill()注解,也需要**EmployeeMapper**做相同操作
代码:
  1. package com.sky.mapper;

  2. @Mapper
  3. public interface CategoryMapper {
  4.     /**
  5.      * 插入数据
  6.      * @param category
  7.      */
  8.     @Insert("insert into category(type, name, sort, status, create_time, update_time, create_user, update_user)" +
  9.             " VALUES" +
  10.             " (#{type}, #{name}, #{sort}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})")
  11.     @AutoFill(value = OperationType.INSERT)
  12.     void insert(Category category);
  13.     /**
  14.      * 根据id修改分类
  15.      * @param category
  16.      */
  17.     @AutoFill(value = OperationType.UPDATE)
  18.     void update(Category category);

  19. }
复制代码
@AutoFill(value = OperationType.INSERT)
    void insert(Category category); //实体记得要放第一位

4.jpg


网站建设,公众号小程序开发,多商户单商户小程序制作,高端系统定制开发,App软件开发联系我们【手机/微信:17817817816
微信扫码

网站建设,公众号小程序开发,商城小程序,系统定制开发,App软件开发等

粤ICP备2024252464号

在本版发帖
微信扫码
QQ客服返回顶部
快速回复 返回顶部 返回列表