这里的代码案例是外卖系统中,用于统一修改新增和更新内容中的更新时间与更新人内容,根据具体情况,在使用时进行自定义修改就行了
第一部分是annotation的,因为是为了自动填充数据准备,所以创建annotation包后,在其中创建了 AutoFill 的注解类型
/**
* 自定义注解,用于标识某个方法需要用于功能字段自动填充处理
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
// 数据库操作类型: UPDATE | INSERT
OperationType value();
}
第二部分是aspect的,其中需要注意的点如下:
1、需要注意获取方法引用的是 import java.lang.reflect.Method; 别引用错了会报错
2、OperationType 是数据库操作类型的一个公共枚举项(最后会附上内容)
3、AutoFillConstant 是公共字段自动填充的常量类(最后会附上内容)
4、BaseContext 是用于存放修改人/创建人 id的,在登录校验中存入信息(最后会附上内容)
/**
* 自定义切面类,实现公共字段自动填充处理逻辑
*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
/**
* 切入点,就是对哪些类,哪些方法进行拦截
* 切点表达式 : 拦截了 mapper包中所有的类和所有的方法 且引入自定义注解,还需要有 AutoFill注解标识
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut() {
}
/**
* 前置通知
* 直接引用之前定义好的切入点
* 在该通知中进行公共字段的赋值
*/
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint) {
log.info("开始进行公共字段的填充");
// 获取被拦截的,当前数据库操作的类型,判断是 UPDATE还是 INSERT
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // 获得方法前面对象
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);// 获得方法上的注解对象
OperationType operationType = autoFill.value(); // 获得数据库操作类型
// 获取当前被拦截的方法的参数-->实体对象
Object[] pointArgs = joinPoint.getArgs();
if (pointArgs == null || pointArgs.length == 0) {
return;
}
Object entity = pointArgs[0];
// 准备赋值的数据
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
// 根据当前操作的类型,为对应的属性通过反射来赋值
if (operationType.equals(OperationType.INSERT)) {
// 为 4个公共字段赋值
// 获得set方法来赋值
try {
Method setCreateTime = entity
.getClass()
.getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method setCreateUser = entity
.getClass()
.getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
Method setUpdateTime = entity
.getClass()
.getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity
.getClass()
.getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
// 通过反射来为对象属性赋值
setCreateTime.invoke(entity, now);
setCreateUser.invoke(entity, currentId);
setUpdateTime.invoke(entity, now);
setUpdateUser.invoke(entity, currentId);
} catch (Exception ex) {
log.info(ex.getMessage());
}
} else {
// 为 2个字段赋值
try {
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, now);
setUpdateUser.invoke(entity, currentId);
} catch (Exception ex) {
log.info(ex.getMessage());
}
}
}
}
OperationType
public enum OperationType {
/**
* 更新操作
*/
UPDATE,
/**
* 插入操作
*/
INSERT
}
AutoFillConstant
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";
}
BaseContext
public class BaseContext {标签:SET,Java,自定义,class,JoinPoint,UPDATE,entity,AutoFillConstant,public From: https://www.cnblogs.com/Lee597/p/18054647
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();
}
}