一、引入
当我们在后端对数据库某个表进行插入或者修改操作时,有时候会遇到插入和修改都要对某些相同的字段进行赋值,比如create_user, create_time, update_user, update_time等字段,一般情况下大多数人都是在后端对实体类进行set操作,但是如果实体类中需要每次都set的字段很多呢?一个个set操作就显得有些low了,下面我将介绍使用切面操作的方法对这些字段进行自动赋值,而无需再进行重复的set操作。
二、步骤
- 先定义一个注解,用来标识需要自动填充的方法,如下代码所示
/**
* 用于需要自定填充字段的方法
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
OperationType value();
}
- 这里的Operation是我自定义的枚举类,用来说明是数据库的何种操作,如下图所示
- 自定义切面类,实现公共字段自动填充的处理逻辑,如下代码
/**
* 自定义切面,实现公共字段自动填充处理逻辑
*/
@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){
log.info("开始进行公共字段的自动填充");
//获取到当前被拦截的方法上的数据库操作类型
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 object=pointArgs[0];
//准备赋值的数据
LocalDateTime time = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
//根据当前不同的操作类型,为对应的属性值通过反射来赋值
Class objectClass = object.getClass();
if(operationType.equals(OperationType.INSERT)){
//四个公共字段
try {
Method method1 = objectClass.getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method method2 = objectClass.getDeclaredMethod(AutoFillConstant.SET_CREATE_USER,Long.class);
Method method3 = objectClass.getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method method4 = objectClass.getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER,Long.class);
method1.invoke(object,time);
method2.invoke(object,currentId);
method3.invoke(object,time);
method4.invoke(object,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}else if(operationType.equals(OperationType.UPDATE)){
//两个公共字段
try {
Method method3 = objectClass.getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method method4 = objectClass.getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER,Long.class);
method3.invoke(object,time);
method4.invoke(object,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
- 其中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";
}
- 在mapper包中需要自动填充的方法上加上自定义注解@AutoFill,比如我的是新增方法和修改方法,然后去掉在serviceimpl中对这些字段的set操作就OK了,之后进行新增和修改操作时就能自动填充这些字段值了。