content: package fun.cmgraph.aspect;
  
  import fun.cmgraph.annotation.AutoFill;
  import fun.cmgraph.constant.AutoFillConstant;
  import fun.cmgraph.context.BaseContext;
  import fun.cmgraph.enumeration.OperationType;
  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.lang.reflect.Method;
  import java.time.LocalDateTime;
  
  @Component
  @Aspect
  @Slf4j
  public class AutoFillAspect {
  
      /**
       * 切入点表达式，封装成一个小方法
       */
      @Pointcut("execution(* fun.cmgraph.mapper.*.*(..)) && @annotation(fun.cmgraph.annotation.AutoFill)")
      public void autoFillPointCut() {
      }
  
      /**
       * 前置通知，在通知中进行公共字段的赋值
       */
      @Before("autoFillPointCut()")  // 调用上面的切入点表达式
      public void autoFill(JoinPoint joinPoint) {
          // 可先进行调试，是否能进入该方法 提前在mapper方法添加AutoFill注解
          log.info("开始进行公共字段(create_time等)的自动填充...");
          // 获取到当前被拦截的方法上的数据库操作类型
          MethodSignature signature = (MethodSignature) joinPoint.getSignature();  // 方法签名对象
          AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class); // 获得方法上的注解对象
          OperationType operationType = autoFill.value(); // 获得数据库操作类型
          // 获取到当前被拦截的方法的参数--实体对象
          Object[] args = joinPoint.getArgs();
          if (args == null || args.length == 0) {
              return;
          }
          Object entity = args[0];
          // 准备赋值的数据：自动填充当前时间
          LocalDateTime now = LocalDateTime.now();
          Integer currentId = BaseContext.getCurrentId();
          // 根据当前不同的操作类型，为对应的属性通过反射来赋值
          if (operationType == OperationType.INSERT) {
              // 为4个公共字段(时间字段)赋值，刚开始插入需要设置create字段
              try {
                  Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Integer.class);
                  Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Integer.class);
                  Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                  Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                  // 通过反射为对象属性赋值
                  setCreateUser.invoke(entity, currentId);
                  setUpdateUser.invoke(entity, currentId);
                  setCreateTime.invoke(entity, now);
                  setUpdateTime.invoke(entity, now);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          } else if (operationType == OperationType.REG) {
              // 为注册的2个公共时间字段赋值，因为一开始无法获得线程id(管理员登录新增员工那个才有)，user字段手动设置100表示自己操作
              try {
                  Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                  Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                  // 通过反射为对象属性赋值
                  setCreateTime.invoke(entity, now);
                  setUpdateTime.invoke(entity, now);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          } else if (operationType == OperationType.UPDATE) {
              // 为2个公共字段赋值
              try {
                  Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Integer.class);
                  Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                  // 通过反射为对象属性赋值
                  setUpdateUser.invoke(entity, currentId);
                  setUpdateTime.invoke(entity, now);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }
  }
  