mybatis公共字段填充(AOP操作)

使用AOP操作数据库,填充公共字段(创建人、修改人、创建时间、修改时间)代码

1、首先导入依赖

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

2、自定义接口

@Target(ElementType.METHOD)//该注解作用在方法上
@Retention(RetentionPolicy.RUNTIME)//注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
public @interface AutoFill {
    //数据库的操作类型:UPDATE INSERT
    OperationType value();
}

3、公共字段相关常量

/**
 * 公共字段自动填充相关常量
 */
public class AutoFillConstant {
    /**
     * 实体类中的方法名称
     */
    public static final String SET_CREATE_TIME = "setCreateTime";
    public static final String SET_UPDATE_TIME = "setUpdateTime";
    public static final String SET_CREATE_USER = "setCreateUser";
    public static final String SET_UPDATE_USER = "setUpdateUser";
    public static final String SET_ID = "setId";
    //微信服务接口地址
    public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";

}

4、threadlocal用来获取当前操作人的id

/**
 * ThreadLocal
 */
public class BaseContext {

    public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    public static void setCurrentId(Long id) {
        threadLocal.set(id);
    }

    public static Long getCurrentId() {
        return threadLocal.get();
    }

    public static void removeCurrentId() {
        threadLocal.remove();
    }

}

5、数据库操作类型枚举类

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

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

    /**
     * 插入操作
     */
    INSERT

}

6、自定义切面

/**
 * 自定义切面(自动填充表格创建人、修改人、创建时间、修改时间)
 *
 * @Author 奕生呀♥
 * @Date 2023/3/13 17:00
 * @Description: 自定义切面(
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
    /**
     * 切入点
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..))&&@annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut() {
    }
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException, InstantiationException {
        //1、获取切入点的方法的参数(Employee的对象)
        Object[] args = joinPoint.getArgs();
        Object arg = args[0];
        //2、获取方法的签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //3、利用反射获取方法上的注解
        AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);
        //4、获取数据库操作类型
        OperationType operationType = annotation.value();
        //5、获取要填充字段的值
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();
        Long snowId =  IdUtil.getSnowflake().nextId();

        //6、判断操作类型:如果是插入操作,插入操作更新四个字段
        //6-1获取操作方法
        if (operationType == OperationType.INSERT) {
            Method setCreateTime = arg.getClass().getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            Method setUpdateTime = arg.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setCreateUser = arg.getClass().getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
            Method setUpdateUser = arg.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            //6-2给对象赋值
            setCreateTime.invoke(arg, now);
            setUpdateTime.invoke(arg, now);
            setCreateUser.invoke(arg, currentId);
            setUpdateUser.invoke(arg, currentId);
            //6-3、暴力获取id值
            Field idField = arg.getClass().getDeclaredField("id");
            idField.setAccessible(true);
            Long id = (Long) idField.get(arg);
            //6-4、如果没有获取到id的值,则填充
            if (id==null){
                idField.set(arg,snowId);
            }
        } else if (operationType == OperationType.UPDATE) {
            Method setUpdateTime = arg.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setUpdateUser = arg.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            setUpdateTime.invoke(arg, now);
            setUpdateUser.invoke(arg, currentId);
        }
    }
}

posted @   奕生呀  阅读(405)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示