diff --git a/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/ClassDescriptionUtil.java b/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/ClassDescriptionUtil.java index ba0ceea66..a63595397 100644 --- a/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/ClassDescriptionUtil.java +++ b/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/ClassDescriptionUtil.java @@ -3,12 +3,14 @@ package cn.stylefeng.roses.kernel.scanner.api.util; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.stylefeng.roses.kernel.rule.enums.FieldTypeEnum; +import cn.stylefeng.roses.kernel.rule.util.ClassTypeUtil; import cn.stylefeng.roses.kernel.scanner.api.context.MetadataContext; -import cn.stylefeng.roses.kernel.scanner.api.enums.FieldMetadataTypeEnum; +import cn.stylefeng.roses.kernel.scanner.api.enums.GenericFieldMetadataType; import cn.stylefeng.roses.kernel.scanner.api.enums.ParamTypeEnum; import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata; import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; /** * 类的元数据描述 @@ -39,8 +41,19 @@ public class ClassDescriptionUtil { if (StrUtil.isNotBlank(paramName)) { fieldMetadataItem.setFieldName(paramName); } - // 设置是否带泛型 - fieldMetadataItem.setGenericFieldMetadataType(FieldMetadataTypeEnum.FIELD.getCode()); + + // 【2024年8月5日新增】判断数组的类型 + fieldMetadataItem.setGenericFieldMetadataType(GenericFieldMetadataType.BASE_TYPE.getCode()); + if (FieldTypeEnum.ARRAY_WITH_OBJECT.equals(fieldTypeEnum)) { + fieldMetadataItem.setGenericFieldMetadataType(GenericFieldMetadataType.OBJECT_TYPE.getCode()); + } + // 如果是集合类型,判断集合的泛型,集合的泛型是对象的话,就是对象类型,否则就是基本类型 + else if (FieldTypeEnum.COLLECTION_WITH_OBJECT.equals(fieldTypeEnum)) { + if (getClassGenObjectFlag(clazz)) { + fieldMetadataItem.setGenericFieldMetadataType(GenericFieldMetadataType.OBJECT_TYPE.getCode()); + } + } + // 设置字段类型,基本、数组、还是object fieldMetadataItem.setFieldType(fieldTypeEnum.getCode()); // 设置当前context构造的参数类型 @@ -63,4 +76,33 @@ public class ClassDescriptionUtil { return createClassMetadata(rawType, fieldTypeEnum, uuid); } + /** + * 获取类的泛型,是否为Object类型 + * + * @author fengshuonan + * @since 2024/8/5 14:36 + */ + public static boolean getClassGenObjectFlag(Class clazz) { + Type genericSuperclass = clazz.getGenericSuperclass(); + return getClassGenObjectFlag(genericSuperclass); + } + + /** + * 获取类的泛型,是否为Object类型 + * + * @author fengshuonan + * @since 2024/8/5 14:36 + */ + public static boolean getClassGenObjectFlag(Type type) { + if (type instanceof ParameterizedType parameterizedType) { + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + if (actualTypeArguments.length > 0) { + Type actualTypeArgument = actualTypeArguments[0]; + FieldTypeEnum classFieldType = ClassTypeUtil.getClassFieldType(actualTypeArgument); + return FieldTypeEnum.OBJECT.equals(classFieldType); + } + } + return false; + } + } diff --git a/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/ClassReflectUtil.java b/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/ClassReflectUtil.java index eb2e10607..0d134eb20 100644 --- a/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/ClassReflectUtil.java +++ b/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/ClassReflectUtil.java @@ -24,18 +24,12 @@ */ package cn.stylefeng.roses.kernel.scanner.api.util; -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ClassUtil; -import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.TypeUtil; -import cn.stylefeng.roses.kernel.rule.annotation.ChineseDescription; -import cn.stylefeng.roses.kernel.scanner.api.enums.FieldMetadataTypeEnum; -import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata; - import java.lang.annotation.Annotation; -import java.lang.reflect.*; -import java.util.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; /** * 类的反射工具 @@ -46,279 +40,26 @@ import java.util.*; public class ClassReflectUtil { /** - * 正在进行解析的Class - */ - private final static Map RUN_MAP = new HashMap<>(2); - - /** - * 获取一个类的所有字段描述 + * 注解转化为string名称 + *

+ * 例如: + * NotBlack注解 > NotBlack * - * @param clazz 类的class类型 - * @return 该类下所有字段的描述信息 * @author fengshuonan - * @since 2020/12/8 18:27 + * @since 2020/12/9 13:39 */ - public static Set getClassFieldDescription(Class clazz) { - HashSet fieldDescriptions = new LinkedHashSet<>(); + public static Set annotationsToStrings(Annotation[] annotations) { + Set strings = new HashSet<>(); - if (clazz == null) { - return fieldDescriptions; + if (annotations == null || annotations.length == 0) { + return strings; } - // 查询本类是否正在进行解析(防止死循环) - String runClassName = RUN_MAP.get(clazz.getName()); - - // 返回null则标识这个类正在运行,则不对该类再进行解析 - if (ObjectUtil.isNotEmpty(runClassName)) { - return null; + for (Annotation annotation : annotations) { + strings.add(annotation.annotationType().getSimpleName()); } - // 获取该类和该类所有父类的属性 - while (clazz != null) { - RUN_MAP.put(clazz.getName(), clazz.getName()); - // 获取类中的所有字段 - Field[] declaredFields = ClassUtil.getDeclaredFields(clazz); - for (Field declaredField : declaredFields) { - // 获取字段元数据 - FieldMetadata fieldDescription = getFieldMetadata(declaredField); - fieldDescriptions.add(fieldDescription); - } - - RUN_MAP.remove(clazz.getName()); - - // 获取本类的父类 - clazz = clazz.getSuperclass(); - } - return fieldDescriptions; - } - - /** - * 获取字段详情 - * - * @param declaredField 字段 - * @return {@link cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata} - * @author majianguo - * @since 2021/6/23 上午10:03 - **/ - private static FieldMetadata getFieldMetadata(Field declaredField) { - // 获取字段的类型 - Class declaredFieldType = declaredField.getType(); - FieldMetadata fieldDescription = createFieldMetadata(declaredFieldType); - - // 获取字段的名称 - String name = declaredField.getName(); - fieldDescription.setFieldName(name); - - // 解析字段类 - fieldClassParsing(declaredField, fieldDescription, declaredFieldType); - - return fieldDescription; - } - - /** - * 字段class类解析 - * - * @author majianguo - * @since 2022/1/6 16:09 - **/ - private static void fieldClassParsing(Field declaredField, FieldMetadata fieldDescription, Class declaredFieldType) { - - // 获取泛型 - Type genericType = declaredField.getGenericType(); - - // 基本类型处理 - if (isPrimitive(declaredFieldType)) { - - // 如果是泛型,则把结果放到集合内 - if (genericType instanceof ParameterizedType) { - - // 读取所有泛型信息解析 - ParameterizedType type = (ParameterizedType) genericType; - Set metadataSet = null; - for (Type actualTypeArgument : type.getActualTypeArguments()) { - Class aClass = TypeUtil.getClass(actualTypeArgument); - // 泛型如果是基本类型则解析基本类型信息,否则什么也不干,最后有泛型的判断解析,这里只处理基本类型 - if (isPrimitive(aClass)) { - FieldMetadata fieldMetadata = baseTypeParsing(declaredField, aClass); - if (metadataSet == null) { - metadataSet = new LinkedHashSet<>(); - } - metadataSet.add(fieldMetadata); - } - } - fieldDescription.setGenericFieldMetadataType(FieldMetadataTypeEnum.GENERIC.getCode()); - fieldDescription.setGenericFieldMetadata(metadataSet); - } - } - - // 处理数组类型 - else if (declaredFieldType.getComponentType() != null) { - declaredFieldType = declaredFieldType.getComponentType(); - if (!isPrimitive(declaredFieldType)) { - fieldDescription.setGenericFieldMetadata(getClassFieldDescription(declaredFieldType)); - } - } - - // 其他类型 - else { - fieldDescription.setGenericFieldMetadata(getClassFieldDescription(declaredFieldType)); - } - - // 获取字段的所有注解 - parsingAnnotation(declaredField, fieldDescription); - - // 该类解析完以后,判断一下会不会是集合嵌套集合的情况,集合嵌套集合就继续下一层解析目前只能解析两层 - if (genericType instanceof ParameterizedType && ((ParameterizedType) genericType).getActualTypeArguments()[0] instanceof ParameterizedType) { - ParameterizedType type = (ParameterizedType) ((ParameterizedType) genericType).getActualTypeArguments()[0]; - Type typeArgument = type.getActualTypeArguments()[0]; - Class typeArgumentItem = TypeUtil.getClass(typeArgument); - FieldMetadata fieldMetadataItem = createFieldMetadata(typeArgumentItem); - fieldMetadataItem.setGenericFieldMetadata(getClassFieldDescription(typeArgumentItem)); - fieldDescription.setGenericFieldMetadataType(FieldMetadataTypeEnum.GENERIC.getCode()); - fieldDescription.getGenericFieldMetadata().iterator().next().setGenericFieldMetadata(Collections.singleton(fieldMetadataItem)); - } - - // 如果是泛型,则解析一下所有泛型 - else if (genericType instanceof ParameterizedType) { - - // 解析泛型字段 - ParameterizedType parameterizedType = (ParameterizedType) genericType; - Set fieldMetadataSet = new LinkedHashSet<>(); - for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { - Class typeClass = TypeUtil.getClass(actualTypeArgument); - FieldMetadata fieldMetadataItem = createFieldMetadata(typeClass); - if (!isPrimitive(typeClass)) { - fieldMetadataItem.setGenericFieldMetadata(getClassFieldDescription(typeClass)); - } else { - FieldMetadata fieldMetadata = baseTypeParsing(declaredField, typeClass); - fieldMetadataItem.setGenericFieldMetadata(Collections.singleton(fieldMetadata)); - } - fieldMetadataSet.add(fieldMetadataItem); - } - - // 查看该类下面是否有字段(有字段找到那个泛型字段进行解析) - Set genericFieldMetadataSet = fieldDescription.getGenericFieldMetadata(); - if (ObjectUtil.isNotEmpty(genericFieldMetadataSet)) { - fieldMetadataGenericFill(genericFieldMetadataSet, declaredFieldType, fieldMetadataSet); - } else { - // 没有字段则把泛型字段添加进去 - fieldDescription.setGenericFieldMetadataType(FieldMetadataTypeEnum.GENERIC.getCode()); - fieldDescription.setGenericFieldMetadata(fieldMetadataSet); - } - } - } - - - /** - * 字段属性填充 - * - * @param genericFieldMetadataSet 类本身的所有字段信息 - * @param declaredFieldType 类本身 - * @param fieldMetadataSet 类的泛型已解析的信息 - * @author majianguo - * @since 2022/1/10 9:46 - **/ - private static void fieldMetadataGenericFill(Set genericFieldMetadataSet, Class declaredFieldType, Set fieldMetadataSet) { - - // 类声明的泛型信息 - Map genericFieldAndNameMap = new HashMap<>(); - TypeVariable>[] typeParameters = declaredFieldType.getTypeParameters(); - if (ObjectUtil.isNotEmpty(typeParameters)) { - Iterator iterator = fieldMetadataSet.iterator(); - for (TypeVariable> typeParameter : typeParameters) { - genericFieldAndNameMap.put(typeParameter.getName(), iterator.next()); - } - } - - // 字段名称和字段信息的映射 - Map fieldAndNameMap = new HashMap<>(genericFieldMetadataSet.size()); - for (FieldMetadata fieldMetadata : genericFieldMetadataSet) { - fieldAndNameMap.put(fieldMetadata.getFieldName(), fieldMetadata); - } - - // 有字段则找到哪些字段用到了泛型 - Field[] declaredFields = ClassUtil.getDeclaredFields(declaredFieldType); - for (Field field : declaredFields) { - Type type = field.getGenericType(); - - // 字段带泛型 - if (type instanceof ParameterizedType) { - ParameterizedType fieldGenericType = (ParameterizedType) type; - Type[] fieldActualTypeArguments = fieldGenericType.getActualTypeArguments(); - for (Type fieldActualTypeArgument : fieldActualTypeArguments) { - FieldMetadata fieldMetadata = genericFieldAndNameMap.get(fieldActualTypeArgument.getTypeName()); - if (ObjectUtil.isNotEmpty(fieldMetadata)) { - FieldMetadata metadata = fieldAndNameMap.get(field.getName()); - if (ObjectUtil.isNotEmpty(metadata)) { - Set metadataSet = new LinkedHashSet<>(); - metadataSet.add(fieldMetadata); - metadata.setGenericFieldMetadata(metadataSet); - } - } - } - } - - // 字段本身就是泛型 - else if (type instanceof TypeVariable) { - FieldMetadata fieldMetadata = genericFieldAndNameMap.get(type.getTypeName()); - if (ObjectUtil.isNotEmpty(fieldMetadata)) { - FieldMetadata metadata = fieldAndNameMap.get(field.getName()); - BeanUtil.copyProperties(fieldMetadata, metadata); - } - } - } - } - - /** - * 解析所有注解 - * - * @author majianguo - * @since 2022/1/7 18:26 - **/ - private static void parsingAnnotation(Field declaredField, FieldMetadata fieldDescription) { - Annotation[] annotations = declaredField.getAnnotations(); - if (annotations != null && annotations.length > 0) { - - // 设置字段的所有注解 - fieldDescription.setAnnotations(annotationsToStrings(annotations)); - - // 遍历字段上的所有注解,找到带groups属性的,按group分类组装注解 - Map> groupAnnotations = new HashMap<>(); - for (Annotation annotation : annotations) { - Class[] validateGroupsClasses = invokeAnnotationMethodIgnoreError(annotation, "groups", Class[].class); - if (validateGroupsClasses != null) { - for (Class validateGroupsClass : validateGroupsClasses) { - addGroupValidateAnnotation(annotation, validateGroupsClass, groupAnnotations); - } - } - } - // 设置分组注解 - fieldDescription.setGroupValidationMessage(groupAnnotations); - - // 填充字段的中文名称 - ChineseDescription chineseDescription = declaredField.getAnnotation(ChineseDescription.class); - if (chineseDescription != null) { - fieldDescription.setChineseName(chineseDescription.value()); - } - } - } - - /** - * 基础类型解析 - * - * @author majianguo - * @since 2022/1/6 16:09 - **/ - private static FieldMetadata baseTypeParsing(Field declaredField, Class actualTypeArgument) { - FieldMetadata item = createFieldMetadata(actualTypeArgument); - item.setFieldName(actualTypeArgument.getName()); - - // 填充字段的中文名称 - ChineseDescription chineseDescription = declaredField.getAnnotation(ChineseDescription.class); - if (null != chineseDescription) { - item.setChineseName(chineseDescription.value()); - } - return item; + return strings; } /** @@ -357,75 +98,4 @@ public class ClassReflectUtil { groupAnnotations.put(validateGroupsClass.getSimpleName(), annotations); } - /** - * 注解转化为string名称 - *

- * 例如: - * NotBlack注解 > NotBlack - * - * @author fengshuonan - * @since 2020/12/9 13:39 - */ - public static Set annotationsToStrings(Annotation[] annotations) { - Set strings = new HashSet<>(); - - if (annotations == null || annotations.length == 0) { - return strings; - } - - for (Annotation annotation : annotations) { - strings.add(annotation.annotationType().getSimpleName()); - } - - return strings; - } - - /** - * 判断类是否是基本类型 - * - * @return {@link boolean} - * @author majianguo - * @since 2022/1/7 10:42 - **/ - private static boolean isPrimitive(Class clazz) { - boolean isPrimitive; - try { - // 基本类型 - if (clazz.isPrimitive()) { - isPrimitive = true; - } else { - // 基本类型包装类 - isPrimitive = ((Class) clazz.getField("TYPE").get(null)).isPrimitive(); - } - } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { - isPrimitive = false; - } - - Package packageObj = clazz.getPackage(); - if (!isPrimitive && ObjectUtil.isNotEmpty(packageObj)) { - isPrimitive = "java.lang".equals(packageObj.getName()) || "java.util".equals(packageObj.getName()) || "java.math".equals(packageObj.getName()); - } - - return isPrimitive; - - } - - - /** - * 根据Class创建字段元数据 - * - * @return {@link FieldMetadata} - * @author majianguo - * @since 2022/1/10 16:11 - **/ - private static FieldMetadata createFieldMetadata(Class typeArgumentItem) { - FieldMetadata fieldMetadataItem = new FieldMetadata(); - fieldMetadataItem.setMetadataId(IdUtil.fastSimpleUUID()); - fieldMetadataItem.setFieldName(typeArgumentItem.getSimpleName()); - fieldMetadataItem.setFieldClassType(typeArgumentItem.getSimpleName()); - fieldMetadataItem.setFieldClassPath(typeArgumentItem.getName()); - fieldMetadataItem.setGenericFieldMetadataType(FieldMetadataTypeEnum.FIELD.getCode()); - return fieldMetadataItem; - } - } diff --git a/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/FieldDescriptionUtil.java b/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/FieldDescriptionUtil.java index 1349da6f3..a18846778 100644 --- a/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/FieldDescriptionUtil.java +++ b/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/util/FieldDescriptionUtil.java @@ -4,14 +4,13 @@ import cn.hutool.core.util.IdUtil; import cn.stylefeng.roses.kernel.rule.annotation.ChineseDescription; import cn.stylefeng.roses.kernel.rule.enums.FieldTypeEnum; import cn.stylefeng.roses.kernel.scanner.api.context.MetadataContext; -import cn.stylefeng.roses.kernel.scanner.api.enums.FieldMetadataTypeEnum; +import cn.stylefeng.roses.kernel.scanner.api.enums.GenericFieldMetadataType; import cn.stylefeng.roses.kernel.scanner.api.enums.ParamTypeEnum; import cn.stylefeng.roses.kernel.scanner.api.factory.ClassDetailMetadataFactory; import cn.stylefeng.roses.kernel.scanner.api.pojo.resource.FieldMetadata; import java.lang.annotation.Annotation; import java.lang.reflect.Field; -import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; @@ -51,10 +50,12 @@ public class FieldDescriptionUtil { parsingAnnotation(field, fieldMetadataItem); // 设置是否带泛型 Type genericType = field.getGenericType(); - if (genericType instanceof ParameterizedType) { - fieldMetadataItem.setGenericFieldMetadataType(FieldMetadataTypeEnum.GENERIC.getCode()); + // 【2024年8月5日新增】更新判断泛型的对象类型的方法 + boolean classGenObjectFlag = ClassDescriptionUtil.getClassGenObjectFlag(genericType); + if (classGenObjectFlag) { + fieldMetadataItem.setGenericFieldMetadataType(GenericFieldMetadataType.OBJECT_TYPE.getCode()); } else { - fieldMetadataItem.setGenericFieldMetadataType(FieldMetadataTypeEnum.FIELD.getCode()); + fieldMetadataItem.setGenericFieldMetadataType(GenericFieldMetadataType.BASE_TYPE.getCode()); } // 设置字段类型,基本、数组、还是object FieldTypeEnum classFieldType = AdvancedClassTypeUtil.getClassFieldType(genericType);