1、自定义注解AutoFill,用于标识需要进行公共字段自动填充的方法
2、自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为公共字段赋值
3、在Mapper的方法上加入AutoFill注解
技术点:枚举、注解、AOP、反射
AOP技术:处理共性逻辑
选择哪一种通知类型?—— 前置通知,增强mapper
选择哪一种切入点表达式?—— @annotation方式
区分是新增还是更新方法?—— 判断方法注解上的属性值
step1:自定义一个枚举类,写下枚举值值用来表示是什么操作
package com.sky.enumeration;
/**
* 数据库操作类型
*/
public enum OperationType {
/**
* 更新操作
*/
UPDATE,
/**
* 插入操作
*/
INSERT
}
step2:自定义公共字段自动填充的注解类
/**
* 简介说明: 自定义公共字段自动填充注解
*
* @author: 小鸥
* @date: 2025/05/06 15:36:33
* @version: 1.0
*/
@Target(ElementType.METHOD) //作用于方法上
@Retention(RetentionPolicy.RUNTIME)// 注解的生命周期
public @interface AutoFill {
//用来表示是新增还是修改
OperationType value();
}
step3:编写一个公共字段自动填充的相关常量
package com.sky.constant;
/**
* 公共字段自动填充相关常量
*/
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";
}
step4:自定义切面类AutoFillAspect
/**
* 简介说明: 公共字段自动填充的切面类
*
* @author: 小鸥
* @date: 2025/05/06 15:44:57
* @version: 1.0
*/
@Aspect //声明这是一个切面类
@Component //将该类交给Spring容器管理
@Slf4j
public class AutoFillAspect {
//前置通知
@Before("@annotation(com.sky.anno.AutoFill)")
public void autoFill(JoinPoint joinPoint){//JoinPoint:连接点 连接点可以获取到当前被拦截的方法的详细信息
//1、获取目标方法上的注解,并拿到注解里面的属性值
MethodSignature signature =(MethodSignature) joinPoint.getSignature();//获取连接点的方法签名对象
Method method = signature.getMethod();//获取到连接点的方法对象
AutoFill annotation = method.getAnnotation(AutoFill.class);//获取到目标方法上的注解对象
OperationType operationType = annotation.value();//获取到注解中的属性值
//2、获取到目标方法的参数对象
Object[] args = joinPoint.getArgs();
if (args == null || args.length == 0){
return;
}
Object entity = args[0];//获取实体参数对象
//3、判断注解中的属性值,如果是insert类型,就补充公共字段的值(四个:创建时间,更新时间,创建人,更新人)
try {
if (operationType == OperationType.INSERT){
//通过反射补充属性值
Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
setCreateTime.invoke(entity,LocalDateTime.now());
setUpdateTime.invoke(entity,LocalDateTime.now());
//BaseContext.getCurrentId() 是一个静态方法,获取当前线程的id
setCreateUser.invoke(entity,BaseContext.getCurrentId());
setUpdateUser.invoke(entity, BaseContext.getCurrentId());
}else {
//4、判断注解中的属性值,如果是update类型,就补充公共字段的值(两个:更新时间,更新人)
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,LocalDateTime.now());
setUpdateUser.invoke(entity, BaseContext.getCurrentId());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}