苍穹外卖复习,切面类实现自动填充

流程

核心概念

自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {

 OperationType value();

}

关键注解

  • @Target(ElementType.METHOD):指定该注解只能用于方法上。
  • @Retention(RetentionPolicy.RUNTIME):指定该注解在运行时保留,可以通过反射读取。

注解属性

  • OperationType value():这是一个属性,类型为 OperationType。通过这个属性,可以指定操作的类型(如插入、更新

切面类  

  • @Aspect:标识该类为一个切面类。

  • @Component:将该类注册为 Spring 容器中的一个 Bean。

  • @Slf4j:使用 Lombok 提供的日志注解,自动生成日志对象 log

@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut(){}
  • 定义了一个切点 autoFillPointCut(),用于匹配满足以下条件的方法:

    • 在 com.sky.mapper 包下的所有类和方法。

    • 方法上标注了 @AutoFill 注解。

  • execution(* com.sky.mapper.*.*(..)):匹配 com.sky.mapper 包下的所有方法。

  • @annotation(com.sky.annotation.AutoFill):匹配标注了 @AutoFill 注解的方法。

@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint){

 @Before("autoFillPointCut()"): 这个注解表示在 autoFillPointCut() 这个切点匹配的方法执行之前,会执行 autoFill 方法

MethodSignature signature = (MethodSignature)joinPoint.getSignature();
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);
OperationType operationType = autoFill.value();
  • joinPoint.getSignature():通过 JoinPoint 获取正在执行的方法的签名(Signature)。Signature 是关于目标方法的信息,例如方法名、返回类型等。
  • (MethodSignature):由于 joinPoint.getSignature() 返回的是一个通用类型 Signature,而你需要操作的是具体的方法签名,因此需要将其强制转换为 MethodSignature,这个类包含了方法签名相关的详细信息。

  • signature.getMethod():通过 MethodSignature 获取目标方法对象(Method),它包含方法的详细信息。
  • getAnnotation(AutoFill.class):从方法对象中获取 @AutoFill 注解实例。如果方法上没有这个注解,返回 null

  • autoFill.value()AutoFill 注解的 value 属性返回的是 OperationType 枚举类型。根据 @AutoFill 注解的定义,value 用来指定当前操作是插入(INSERT)还是更新(UPDATE)。通过这行代码,你能够得到这个操作类型。

Object[] args = joinPoint.getArgs();
if (args == null || args.length == 0) {
    return;
}
Object entity = args[0];

  • 获取方法的参数,实体对象,假设第一个参数是实体对象。如果参数为空,直接返回,不进行任何处理。

 填充公共字段(INSERT 和 UPDATE)

if(operationType == OperationType.INSERT){
    try {
        Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
        Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
        Method setCreateUserId = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
        Method setUpdateUserId = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

        setCreateTime.invoke(entity,now);
        setUpdateTime.invoke(entity,now);
        setCreateUserId.invoke(entity,currentId);
        setUpdateUserId.invoke(entity,currentId);

    } catch (Exception e) {
        throw new RuntimeException(e);
    }
  • 反射机制getDeclaredMethod 用来获取指定方法名称及参数类型的 Method 对象。这里,我们通过反射获取实体类的 setter 方法(即 setCreateTimesetUpdateTimesetCreateUserId 和 setUpdateUserId)。

    • entity.getClass() 是获取实体对象的 Class 对象,代表当前实体类的元数据。
    • AutoFillConstant.SET_CREATE_TIME 等是常量,代表方法的名称(如 setCreateTime),这些方法名称通常会事先定义好。
    • LocalDateTime.class 和 Long.class 是方法参数的类型,用于匹配 setter 方法的参数类型.class 是一个关键字,它用于获取一个类的 Class 对象。Class 对象不仅代表了该类本身,而且还提供了该类的详细信息。。
  • invoke 方法:通过 Method 对象的 invoke 方法调用相应的 setter 方法,传入相应的参数值(如当前时间 now 和当前用户ID currentId)。

    • setCreateTime.invoke(entity, now) 会调用实体类的 setCreateTime(LocalDateTime) 方法,并传入当前时间 now
    • 类似的,setUpdateTime.invoke(entity, now) 调用 setUpdateTime(LocalDateTime),并传入当前时间。
    • setCreateUserId.invoke(entity, currentId) 和 setUpdateUserId.invoke(entity, currentId) 分别调用 setCreateUserId(Long) 和 setUpdateUserId(Long),并传入当前用户ID。
    • Object obj: 目标对象,表示你要调用方法的实例。对于静态方法,这个参数可以是 null
    • Object... args: 方法的参数列表,使用可变参数形式传入。根据方法签名的不同,args 中的元素会被传递到目标方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值