AOP切面编程:公共字段的自动填充

欢迎来到“雪碧聊技术”CSDN博客!

在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将不断探索Java的深邃世界,分享最新的技术动态、实战经验以及项目心得。

让我们一同在Java的广阔天地中遨游,携手提升技术能力,共创美好未来!感谢您的关注与支持,期待在“雪碧聊技术”与您共同成长!

目录

一、什么叫公共字段?

举例

二、为什么要进行公共字段填充?

1、不这么做的缺点

2、公共字段填充的实现思路

三、具体是如何实现的?

1、定义一个注解AutoFill,用来标志mapper接口的哪些方法需要进行公共字段填充

2、给需要公共字段自动填充的方法,添加该注解

3、编写切面类AutoFillAspect

4、之后对应的方法,会携带填充完的、更加完善的实体类,进入mapper.xml中进行sql操作。

结语


一、什么叫公共字段?

举例

下面几张表,都包含了创建时间、修改时间、创建人ID、修改人ID。

此时这四个字段,就叫公共字段。

二、为什么要进行公共字段填充?

1、不这么做的缺点

如果不进行公共字段填充,就需要在service层,手动地给添加/修改的对象的这四个字段进行填充,会造成代码臃肿、重复,不是明智的选择。

而我们使用AOP切面编程,会在这几张表相关的所有insert、update操作语句执行之前,自动完成公共字段填充。

2、公共字段填充的实现思路

通过切入点表达式,捕获到所有需要进行公共字段填充的方法,给这些方法加一个前置通知:即,在进行insert、update操作之前,要先获取操作的实体类,给这个实体类的4个公共字段(创建时间、修改时间、创建人ID、修改人ID)进行填充。

三、具体是如何实现的?

1、定义一个注解AutoFill,用来标志mapper接口的哪些方法需要进行公共字段填充

2、给需要公共字段自动填充的方法,添加该注解

3、编写切面类AutoFillAspect

  • 通过切入点表达式,来捕获到对应的连接点(即:需要被AOP切面类操作的方法)。
  • 添加前置通知
  • 约定这些方法的第一个形参,就是要insert/update操作的实体类
  • 获取该实体类
  • 准备要赋值的数据,如:当前时间、当前人员的ID(如管理员id)
  • 根据注解上的操作类型,来执行不同的逻辑
  • 如果是insert类型,就给该实体类加上创建时间、更新时间、创建人ID、更新人ID这四个字段。如果是update类型,就给该实体类加上更新时间、更新人ID这两个字段(因为之前该条数据已经有创建时间、创建人ID这两个字段了)。
/**
 * 自定义切面,实现公共字段自动填充处理逻辑
 */
@Aspect //表明这是一个切面类
@Component //表明这也是一个Bean,需要交给spring容器来管理(IOC控制反转)
@Slf4j //方便进行日志记录(lombok)
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("开始进行公共字段自动填充...");

        //-:获取到当前被拦截的方法上的数据库操作类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解
        OperationType operationType = autoFill.value();//获得该注解操作类型是update还是insert

        //-:获取到当前被拦截的方法的参数
        Object[] args = joinPoint.getArgs();
        if(args == null || args.length == 0){
            return;
        }
        //自己约定的规则(insert/update的对象,一定放在形参列表的第一个)这一点十分重要。
        Object entity = args[0];

        //-:准备赋值的数据:当前时间、当前用户的id
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();

        //-:根据当前不同的操作类型,为对应的属性通过反射来赋值
        //如果方法是添加操作(第一种可能)
        if(operationType == OperationType.INSERT){
            //-:为4个公共字段赋值
            try {
                //-:通过反射,获取到对应的set方法(方法名+形参类型, 这样能避免方法重载问题)
                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);

                //-:通过反射,调用构造器,为该entity对象属性赋值,然后就可以携带进入Mapper.xml进行sql操作了
                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 {
                //-:通过反射,获取到对应的set方法
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

                //-:通过反射,调用set方法,为该entity对象的属性(公共字段)赋值,然后就可以携带进Mapper.xml进行sql操作了
                setUpdateTime.invoke(entity, now);
                setUpdateUser.invoke(entity, currentId);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}

4、之后对应的方法,会携带填充完的、更加完善的实体类,进入mapper.xml中进行sql操作。

结语

以上就是使用AOP切面编程,实现公共字段自动填充的步骤,想了解更多的Java开发知识,请关注本博主~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值