对于时间属性,如createTime、updateTime在进行插入、修改操作时都要一个个初始化处理,过于麻烦。
可以自定义注解@AutoFill作用于INSERT,UPDATE操作方法上,再自定义切面类,统一拦截加入了AutoFill注解的方法,通过反射为公共字段赋值。
涉及知识点:枚举、注解、AOP、反射
目录
1.自定义注解@AutoFill, 用于标示某个方法需要进行功能字段自动填充处理
2.在Mapper层对应insert、update方法上加上注解@AutoFill
3.自定义切面,实现公共字段自动填充处理逻辑
老办法,缺点:过于重复和麻烦
好方法:公共字段自动填充
1.自定义注解@AutoFill, 用于标示某个方法需要进行功能字段自动填充处理
自定义注解:AutoFill
import com.sky.enumeration.OperationType;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义注解,用于标示某个方法需要进行功能字段自动填充处理*/
@Target(ElementType.METHOD) // 只能用于标注方法
@Retention(RetentionPolicy.RUNTIME) // 运行时有效
public @interface AutoFill {// 枚举数据库类型:UPDATE INSERT 用于标示自动填充的类型OperationType value();
}
自定义枚举类型:OperationType
/*** 数据库操作类型*/
public enum OperationType {/*** 更新操作*/UPDATE,/*** 插入操作*/INSERT}
2.在Mapper层对应insert、update方法上加上注解@AutoFill
3.自定义切面,实现公共字段自动填充处理逻辑
①定义切入点,即统一拦截加入了AutoFill 注解的方法
②编写前置通知,进行公共字段自动填充
-
获取到当前被拦截的方法上的数据库操作类型
-
获取到当前被拦截的方法的参数--实体对象
-
准备赋值的数据
-
根据当前不同的操作类型,为对应的属性通过反射来赋值
自定义切面类:AutoFillAspect
import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.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;/*** 自定义切面,实现公共字段自动填充处理逻辑*/
@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("开始进行公共字段自动填充...");//1. 获取到当前被拦截的方法上的数据库操作类型MethodSignature signature = (MethodSignature)joinPoint.getSignature(); //方法签名对象AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class); //获得方法上的对象OperationType operationType = autoFill.value(); //获取数据库操作类型//2. 获取到当前被拦截的方法的参数--实体对象Object[] args = joinPoint.getArgs();if (args == null || args.length == 0){return;}Object entity = args[0];//3. 准备赋值的数据LocalDateTime now = LocalDateTime.now();Long currentId = BaseContext.getCurrentId();//4. 根据当前不同的操作类型,为对应的属性通过反射来赋值if (operationType == OperationType.INSERT){// 为4个公共字段赋值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 e) {e.printStackTrace();}} else if (operationType == OperationType.UPDATE){// 为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 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";
}