AOP和反射的使用——自动填充公共字段

发布时间 2023-09-17 20:27:52作者: 凌碎瞳缘

  在写业务代码时候,我们经常会在业务层对数据实体进行一些重复的传参,例如更新日期时间。这太麻烦了,为了减轻代码量,我们可以利用AOP和反射对代码进行一些调整,免去这些重复操作。也帮助我们对反射的实际应用有一定认识。

 

  首先自定义一个注解

@Target(ElementType.METHOD)//指定该注解需要加在什么地方,这里设置是加在方法上
@Retention(RetentionPolicy.RUNTIME)//指定该注解保留多久,这里设置是一直保留到jvm加载class文件后仍然保留
public @interface AutoFill {
    OperationType value();
}

   

  书写切面类AOP,将注解定义在mapper层方法中,在方法执行之前将参数传入

@Aspect
@Component//一定要记得将AOP加入IOC容器中
@Slf4j
public class AutoFillAspect {

    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointcut(){};

    @Before("autoFillPointcut()")
    public void autoFill(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//Signature中没有getMethod()方法,所以转为子接口去调用
        AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);
        OperationType operationType=annotation.value();

        Object[] entity = joinPoint.getArgs();//获取方法的所有参数

        if (entity==null || entity.length==0)return;//一般不会出现这个情况

        //这里需要说明一点,枚举类在大多数情况下是可以用==替代equals()的,且性能会更好些。
        //但需要注意的是,==不会抛出 NullPointerException 异常,且==在编译期间会检测a与b的类型兼容性
        if (operationType==OperationType.INSERT){
            try {//getDeclaredMethod()和invoke()可能会抛异常
                Method setCreateTime = entity[0].getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);//利用反射获取对象方法,传入方法名和参数类型
                Method setUpdateTime = entity[0].getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);

                setCreateTime.invoke(entity[0], LocalDateTime.now());//利用反射调用entity[0]的setCreateTime方法,传参
                setUpdateTime.invoke(entity[0], LocalDateTime.now());

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (operationType==OperationType.UPDATE) {
            try {//getDeclaredMethod()和invoke()可能会抛异常
                Method setUpdateTime = entity[0].getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);

                setUpdateTime.invoke(entity[0], LocalDateTime.now());

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

}