xChar

场景描述

  • 根据注解 SealAuthId 去查找要标记位的属性,并修改其值

  • 如果直属属性中没有修改的属性,而是在其子孙属性中,则通过 SealAuthId (CONTAIN) 引导程序到子属性中去查找

  • 直到找到标记 SealAuthId (AUTH_ID) 的属性,执行修改方法

标记属性

待处理对象

@Data
public class YcDTO {
    @SealAuthId(type = SealAuthId.CONTAIN)
    @Valid
    @NotEmpty(message = "信息列表[dataList]不能为空")
    private List<YcSignatories> dataList;
}

子对象

@Data
public class YcSignatories {
    @SealAuthId
    @NotBlank(message = "编码[sealId]不能为空")
    private String sealId;
}

注解查找

/**
  * 找到dto对象中注解标记的 SealAuthId(AUTH_ID) 并执行方法 function
  * @param dto 待查找的对象
  * @param function 找到注解标记后执行的方法
  */
public static void findAnnotationAndDo(Object dto, Function function) {
    if (Objects.isNull(dto)){
        log.debug("dto is NULL");
        return;
    }
    Class<?> parameterObjectClass = dto.getClass();
    Field[] fields = parameterObjectClass.getDeclaredFields();
    for (Field field : fields){
        SealAuthId sealAuthId = AnnotationUtils.findAnnotation(field, SealAuthId.class);
        if (Objects.nonNull(sealAuthId)){
            log.debug("查找到注解@SealAuthId[{}]", field.getName());
            if (SealAuthId.AUTH_ID.equals(sealAuthId.type())){
                annotateParameterDo(dto, field, function);
            } else if (SealAuthId.CONTAIN.equals(sealAuthId.type())){
                annotateContainSearch(dto, field, function);
            }
        }
    }
}

/**
  * 查找到包含注解的对象,准备进行下一步查找
  * 在标记 CONTAIN 属性中继续查找,直到查找到标记 AUTH_ID
  * @param dto 待查找的对象
  * @param function 找到注解标记 AUTH_ID 后执行的方法
  * @param field 注解标记为“CONTAIN”的属性
  */
private static void annotateContainSearch(Object dto, Field field, Function function) {
    try {
        if (!field.isAccessible()){
            field.setAccessible(true);
        }
        Object objContain = field.get(dto);
        if (Objects.isNull(objContain)){
            log.debug("{} is NULL, continue.", field.getName());
            return;
        }
        // 属性有值
        if (Collection.class.isAssignableFrom(field.getType())){
            log.debug("{} is collection", field.getName());
            Iterator iterator = ((Collection) objContain).iterator();
            while (iterator.hasNext()){
                // 遍历查询集合中的对象中的注解
                // 因为是从请求参数中反序列化得来的,暂时不考虑循环引用问题
                findAnnotationAndDo(iterator.next(), function);
            }
        } else {
            log.debug("{} is obj", field.getName());
            // 因为是从请求参数中反序列化得来的,暂时不考虑循环引用问题
            findAnnotationAndDo(objContain, function);
        }
    } catch (IllegalAccessException e) {
        log.error(e.getMessage());
    }
}

/**
  * 查找到注解标记 AUTH_ID 的属性,执行操作
  * @param dto 待查找的对象
  * @param function 找到注解标记 AUTH_ID 后执行的方法
  * @param field 注解标记为 AUTH_ID 的属性
  */
private static void annotateParameterDo(Object dto, Field field, Function function) {
    if (!field.isAccessible()){
        field.setAccessible(true);
    }
    try {
        // 原值
        Object localValue = field.get(dto);
        if (Objects.nonNull(function)){
            // 修改值的方法效用
            Object apply = function.apply(localValue);
            // 通过对象的setter方法重置属性的值
            field.set(dto, apply);
            log.info("修改注解标记的{}: {} => {}", field.getName(), localValue, apply);
        }
    } catch (IllegalAccessException e) {
        log.error(e.getMessage());
    }
}

方法调用

public void defaultBind(Object[] params, SealBind sealBind){
    Object param = params[0];
    SealAuthUtils.findAnnotationAndDo(param, sealCode -> {
        if (Objects.nonNull(sealCode) && sealCode instanceof String){
            return findSealCodeByAuthId((String) sealCode, sealBind);
        }
        // 维持不变
        return sealCode;
    });
}
Loading comments...