[SpringBoot]自定义注解@AutoFill,实现公共字段自动填充(避免重复对时间属性初始化

对于时间属性,如createTime、updateTime在进行插入、修改操作时都要一个个初始化处理,过于麻烦。

可以自定义注解@AutoFill作用于INSERT,UPDATE操作方法上,再自定义切面类,统一拦截加入了AutoFill注解的方法,通过反射为公共字段赋值。

涉及知识点:枚举、注解、AOP、反射

目录

1.自定义注解@AutoFill, 用于标示某个方法需要进行功能字段自动填充处理

2.在Mapper层对应insert、update方法上加上注解@AutoFill 

3.自定义切面,实现公共字段自动填充处理逻辑


 

老办法,缺点:过于重复和麻烦 

[SpringBoot]自定义注解@AutoFill,实现公共字段自动填充(避免重复对时间属性初始化_第1张图片

好方法:公共字段自动填充

1.自定义注解@AutoFill, 用于标示某个方法需要进行功能字段自动填充处理

[SpringBoot]自定义注解@AutoFill,实现公共字段自动填充(避免重复对时间属性初始化_第2张图片 

自定义注解: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 

[SpringBoot]自定义注解@AutoFill,实现公共字段自动填充(避免重复对时间属性初始化_第3张图片

[SpringBoot]自定义注解@AutoFill,实现公共字段自动填充(避免重复对时间属性初始化_第4张图片

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";
}

 

你可能感兴趣的:(Springboot,spring,boot,java,spring)