diff --git a/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/enums/FieldMetadataTypeEnum.java b/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/enums/FieldMetadataTypeEnum.java new file mode 100644 index 000000000..ad15865e1 --- /dev/null +++ b/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/enums/FieldMetadataTypeEnum.java @@ -0,0 +1,54 @@ +/* + * Copyright [2020-2030] [https://www.stylefeng.cn] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Guns采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Guns源码头部的版权声明。 + * 3.请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://gitee.com/stylefeng/guns + * 5.在修改包名,模块名称,项目代码等时,请注明软件出处 https://gitee.com/stylefeng/guns + * 6.若您的项目无法满足以上几点,可申请商业授权 + */ +package cn.stylefeng.roses.kernel.scanner.api.enums; + +import lombok.Getter; + +/** + * 字段元数据类型 + * + * @author majianguo + * @date 2022/1/11 9:25 + */ +@Getter +public enum FieldMetadataTypeEnum { + + /** + * 字段 + */ + FIELD(1), + + /** + * 泛型 + */ + GENERIC(2); + + FieldMetadataTypeEnum(Integer code) { + this.code = code; + } + + private final Integer code; + +} diff --git a/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/pojo/resource/FieldMetadata.java b/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/pojo/resource/FieldMetadata.java index da6335648..53859f3f9 100644 --- a/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/pojo/resource/FieldMetadata.java +++ b/kernel-d-scanner/scanner-api/src/main/java/cn/stylefeng/roses/kernel/scanner/api/pojo/resource/FieldMetadata.java @@ -92,6 +92,12 @@ public class FieldMetadata { @ChineseDescription("校验信息的提示信息") private String validationMessages; + /** + * 泛型或object类型的字段的描述类型(1-字段,2-泛型) + */ + @ChineseDescription("泛型或object类型的字段的描述(1-字段,2-泛型)") + private Integer genericFieldMetadataType; + /** * 泛型或object类型的字段的描述 */ 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 b391b987f..15bf9d26d 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,20 +24,19 @@ */ 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.scanner.api.annotation.field.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 static java.util.Comparator.comparing; -import static java.util.stream.Collectors.toCollection; - /** * 类的反射工具 * @@ -114,17 +113,17 @@ public class ClassReflectUtil { * @date 2020/12/8 18:27 */ public static Set getClassFieldDescription(Class clazz) { - HashSet fieldDescriptions = new HashSet<>(); + HashSet fieldDescriptions = new LinkedHashSet<>(); if (clazz == null) { return fieldDescriptions; } // 查询本类是否正在进行解析(防止死循环) - String runing = RUN_MAP.get(clazz.getName()); + String runClassName = RUN_MAP.get(clazz.getName()); // 返回null则标识这个类正在运行,则不对该类再进行解析 - if (ObjectUtil.isNotEmpty(runing)) { + if (ObjectUtil.isNotEmpty(runClassName)) { return null; } @@ -144,7 +143,7 @@ public class ClassReflectUtil { // 获取本类的父类 clazz = clazz.getSuperclass(); } - return fieldDescriptions.stream().collect(toCollection(() -> new TreeSet<>(comparing(FieldMetadata::getFieldName)))); + return fieldDescriptions; } /** @@ -156,20 +155,14 @@ public class ClassReflectUtil { * @date 2021/6/23 上午10:03 **/ private static FieldMetadata getFieldMetadata(Field declaredField) { - FieldMetadata fieldDescription = new FieldMetadata(); - - // 生成uuid,给前端用 - fieldDescription.setMetadataId(IdUtil.fastSimpleUUID()); + // 获取字段的类型 + Class declaredFieldType = declaredField.getType(); + FieldMetadata fieldDescription = createFieldMetadata(declaredFieldType); // 获取字段的名称 String name = declaredField.getName(); fieldDescription.setFieldName(name); - // 获取字段的类型 - Class declaredFieldType = declaredField.getType(); - fieldDescription.setFieldClassType(declaredFieldType.getSimpleName()); - fieldDescription.setFieldClassPath(declaredFieldType.getName()); - // 解析字段类 fieldClassParsing(declaredField, fieldDescription, declaredFieldType); @@ -207,6 +200,7 @@ public class ClassReflectUtil { metadataSet.add(fieldMetadata); } } + fieldDescription.setGenericFieldMetadataType(FieldMetadataTypeEnum.GENERIC.getCode()); fieldDescription.setGenericFieldMetadata(metadataSet); } } @@ -227,34 +221,106 @@ public class ClassReflectUtil { // 获取字段的所有注解 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); - fieldDescription.getGenericFieldMetadata().iterator().next().setGenericFieldMetadata(getClassFieldDescription(typeArgumentItem)); + 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)) { - Set classFieldDescription = getClassFieldDescription(typeClass); - if (null != classFieldDescription) { - fieldMetadataSet.addAll(classFieldDescription); - } + fieldMetadataItem.setGenericFieldMetadata(getClassFieldDescription(typeClass)); } else { FieldMetadata fieldMetadata = baseTypeParsing(declaredField, typeClass); - fieldMetadataSet.add(fieldMetadata); + 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 + * @date 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()); + 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); + } + } + } + } + /** * 解析所有注解 * @@ -296,10 +362,9 @@ public class ClassReflectUtil { * @date 2022/1/6 16:09 **/ private static FieldMetadata baseTypeParsing(Field declaredField, Class actualTypeArgument) { - FieldMetadata item = new FieldMetadata(); - item.setMetadataId(IdUtil.fastSimpleUUID()); + FieldMetadata item = createFieldMetadata(actualTypeArgument); item.setFieldName(actualTypeArgument.getName()); - item.setFieldClassType(actualTypeArgument.getTypeName()); + // 填充字段的中文名称 ChineseDescription chineseDescription = declaredField.getAnnotation(ChineseDescription.class); if (null != chineseDescription) { @@ -396,5 +461,23 @@ public class ClassReflectUtil { return isPrimitive; } - + + + /** + * 根据Class创建字段元数据 + * + * @return {@link FieldMetadata} + * @author majianguo + * @date 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; + } + }