自定义AOP自动注入公共字段
自定义注解
/**
* 自定义注解,用于标识某个方法需要进行功能字段自动填充处理
*/
@Target(ElementType.METHOD) // 指定当前注解的位置,ElementType.METHOD表示该注解只能加在方法上
@Retention(RetentionPolicy.RUNTIME) // 固定写法
public @interface AutoFill {
//数据库操作类型:UPDATE INSERT
OperationType value();
}
/**
* 数据库操作类型
*/
public enum OperationType {
/**
* 更新操作
*/
UPDATE,
/**
* 插入操作
*/
INSERT
}
/**
* 公共字段自动填充相关常量
*/
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";
}
/**
* 插入员工数据
* @param employee
*/
@Insert("insert into employee (name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user, status)" + "values" +
"(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})")
@AutoFill(value = OperationType.INSERT)
void insert(Employee employee);
自定义AOP类
/**
* 自定义切面,实现公共字段自动填充处理逻辑
*/
@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("开始进行公共字段字段填充...");
//获取到当前被拦截的方法上的数据库操作类型,如果是insert要更新四个字段,是update只要更新两个字段
MethodSignature signature =(MethodSignature) joinPoint.getSignature(); //方法签名对象
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象
OperationType operationType = autoFill.value(); //获取数据库操作类型
//获取到当前被拦截的方法的参数--实体对象
Object[] args = joinPoint.getArgs();
// 判空,防止空指针
if (args == null || args.length == 0){ // 更新或插入操作不提供待更新对象,直接返回不管了
return;
}
Object entity = args[0]; // 本项目中,无论是controller的请求参数和返回值都封装成一个实体,这里获取第一个参数,就约定项目中所有@AutoFill注解的方法把待更新的实体参数都放在第一个位置
//准备赋值的数据
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
//根据当前不同的操作类型,为对应的属性通过反射来赋值
// 如果@AutoFill为INSERT
if ((operationType == OperationType.INSERT)){
//为四个公共字段赋值
try {
// 通过实体类的getter方法为字段赋值
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){
//为两个公共字段赋值
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();
}
}
}
自定义元数据处理器自动注入公共字段
/**
* 自定义元数据处理器,与实体类中@TableFiled对应使用
*/
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 插入操作字段填充
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("公共字段自动填充[insert]...");
log.info(metaObject.toString());
if(metaObject.hasSetter("createTime"))
metaObject.setValue("createTime", LocalDateTime.now());
if(metaObject.hasSetter("updateTime"))
metaObject.setValue("updateTime", LocalDateTime.now());
if(metaObject.hasSetter("createUser"))
metaObject.setValue("createUser", BaseContext.getCurrentId());
if(metaObject.hasSetter("updateUser"))
metaObject.setValue("updateUser", BaseContext.getCurrentId());
}
/**
* 更新操作自动填充
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
Long id = Thread.currentThread().getId();
log.info("线程id为:{}", id);
log.info("公共字段自动填充[update]...");
log.info(metaObject.toString());
if(metaObject.hasSetter("updateTime"))
metaObject.setValue("updateTime", LocalDateTime.now());
if(metaObject.hasSetter("updateUser"))
metaObject.setValue("updateUser", BaseContext.getCurrentId());
}
}
/**
* 员工实体类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String name;
private String password;
private String phone;
private String sex;
private String idNumber;
private Integer status;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
}