002_公共字段公共填充

每次进行增加员工或者修改员工之类,有关修改和新增的操作时,要对修改时间、新增时间、修改人、新增人这几个字段进行修改,代码比较重复。

用切面,前置通知,对Mapper中的方法进行捕获。这些都是我们操作的对象中的字段,原本这些字段是在service的实现类中进行赋值。

用注解进行标识,有@AutoFill就表示当前方法要进行捕获,捕获了之后就把那几个字段进行修改。代码只用写一份,只要有注解就会执行这个进行公共属性赋值的代码。

step1 自定义注解AutoFill,用于表示需要进行公共字段自动填充的方法

/**
 * 自定义注解
 * 用于表示某个方法需要进行字段自动填充
 */
@Target(ElementType.METHOD) //表示用于方法的标识
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {

    //数据库操作类型:UPDATE、INSERT  update和insert要赋值的属性数量不一样,定义这个属性可以用于区分
    OperationType value();//注解的属性
}

step2 自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为对象属性赋值

/**
 * 自定义切面
 * 实现公共字段自动填充处理逻辑
 */
@Aspect
@Component //交给spring容器来管理
@Slf4j
public class AutoFillAspect {

    /**
     * 切入点
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)") //匹配mapper包下的所有类下的所有方法中的 有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();//获得数据库操作类型

        //获取到当前被拦截的方法的参数--实体对象
        //这个对象已经在service的实现类中被操作过了 例如员工新增这个操作,账号姓名性别等等这些是属性已经在serviceImpl中进行赋值了,但是修改时间、新增时间..这些属性是公共属性、是重复的,我们放到mapper中进行赋值。将mapper中的新增员工方法拦截,然后加上注解,就可以执行这里的代码了。
        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){
            try {
                //获取到实体类中的setter操作的方法
                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();
            }
        }
        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();
            }
        }

    }
}

step3 在Mapper的方法上加入AutoFill注解

@AutoFill(OperationType.UPDATE)
void update(Employee employee);

为什么注解加载了mapper中,我的理解是:

serviceImpl中传入的对象是前端传过来的封装好的对象,然后我们会将其封装成实体类,传给mapper,最终在mapper中的方法的参数是我们需要的实体类,最终传入数据库的就是这个实体类。如果采用前置通知,在mapper中的方法执行之前进行最后的封装,这才是完整的实体类。如果要将注解用在serviceImpl中的话,应该采用的是后置通知吧。

posted @   平平无奇的five  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示