1、自定义注解
package com.sky.annotation;
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();
}
创建一个枚举类,用于指定类型
package com.sky.enumeration;
/**
* 数据库操作类型
*/
public enum OperationType {
/**
* 更新操作
*/
UPDATE,
/**
* 插入操作
*/
INSERT
}
2、自定义切面类
package com.sky.aspect;
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.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
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 // 将切面类加入IOC容器
@Slf4j // 自动生成日志对象
public class AutoFillAspect {
/**
* 切入点
* <p>
* 定义切点表达式
* execution 是指扫描该包下的所有类以及所有方法
*
* @annotation 是指带有该注解的方法
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut() {
}
/**
* 前置通知,在通知中进行公共字段的赋值
* <p>
* JoinPoint 获取到被拦截的方法信息
* 指定切入点,当匹配到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[] args = joinPoint.getArgs();
if (args == null || args.length == 0) {
return;
}
Object entity = args[0];
// 准备赋值的数据
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
// 根据当前不同的操作类型,为对应的属性通过反射来赋值
if (operationType == OperationType.INSERT){
// 为4个公共字段赋值
try {
Method createTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method createUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
Method updateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method updateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
// 通过反射为对象属性赋值
createTime.invoke(entity, now);
createUser.invoke(entity, currentId);
updateTime.invoke(entity, now);
updateUser.invoke(entity, currentId);
} catch (Exception e) {
throw new RuntimeException(e);
}
}else if (operationType == OperationType.UPDATE){
// 为2个公共字段赋值
try {
Method updateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method updateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
// 通过反射为对象属性赋值
updateTime.invoke(entity, now);
updateUser.invoke(entity, currentId);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
创建公共字段自动类
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";
}
3、使用
/**
* 插入数据
* @param category
*/
@AutoFill(value = OperationType.INSERT)
void insert(Category category);
/**
* 根据id修改分类
* @param category
*/
@AutoFill(value = OperationType.UPDATE)
void update(Category category);