/* * Copyright (c) 2011-2021, baomidou (jobob@qq.com). * * 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. */ package com.github.yulichang.toolkit; import com.baomidou.mybatisplus.core.toolkit.*; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.springframework.core.GenericTypeResolver; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.security.AccessController; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import java.util.stream.Stream; import static java.util.function.Function.identity; import static java.util.stream.Collectors.toMap; /** * 反射工具类,提供反射相关的快捷操作 * * @author Caratacus * @author hcl * @since 2016-09-22 */ @SuppressWarnings("unused") public final class ReflectionKit { private static final Log logger = LogFactory.getLog(ReflectionKit.class); /** * class field cache */ private static final Map, List> CLASS_FIELD_CACHE = new ConcurrentHashMap<>(); private static final Map, Class> PRIMITIVE_WRAPPER_TYPE_MAP = new IdentityHashMap<>(8); private static final Map, Class> PRIMITIVE_TYPE_TO_WRAPPER_MAP = new IdentityHashMap<>(8); static { PRIMITIVE_WRAPPER_TYPE_MAP.put(Boolean.class, boolean.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Byte.class, byte.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Character.class, char.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Double.class, double.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Float.class, float.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Integer.class, int.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Long.class, long.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Short.class, short.class); for (Map.Entry, Class> entry : PRIMITIVE_WRAPPER_TYPE_MAP.entrySet()) { PRIMITIVE_TYPE_TO_WRAPPER_MAP.put(entry.getValue(), entry.getKey()); } } /** * 获取字段值 * * @param entity 实体 * @param fieldName 字段名称 * @return 属性值 */ public static Object getFieldValue(Object entity, String fieldName) { Class cls = entity.getClass(); Map fieldMaps = getFieldMap(cls); try { Field field = fieldMaps.get(fieldName); Assert.notNull(field, "Error: NoSuchField in %s for %s. Cause:", cls.getSimpleName(), fieldName); field.setAccessible(true); return field.get(entity); } catch (ReflectiveOperationException e) { throw ExceptionUtils.mpe("Error: Cannot read field in %s. Cause:", e, cls.getSimpleName()); } } /** *

* 反射对象获取泛型 *

* * @param clazz 对象 * @param genericIfc 所属泛型父类 * @param index 泛型所在位置 * @return Class */ public static Class getSuperClassGenericType(final Class clazz, final Class genericIfc, final int index) { Class[] typeArguments = GenericTypeResolver.resolveTypeArguments(ClassUtils.getUserClass(clazz), genericIfc); return null == typeArguments ? null : typeArguments[index]; } /** *

* 获取该类的所有属性列表 *

* * @param clazz 反射类 */ public static Map getFieldMap(Class clazz) { List fieldList = getFieldList(clazz); return CollectionUtils.isNotEmpty(fieldList) ? fieldList.stream().collect(Collectors.toMap(Field::getName, field -> field)) : Collections.emptyMap(); } /** *

* 获取该类的所有属性列表 *

* * @param clazz 反射类 */ public static List getFieldList(Class clazz) { if (Objects.isNull(clazz)) { return Collections.emptyList(); } return CollectionUtils.computeIfAbsent(CLASS_FIELD_CACHE, clazz, k -> { Field[] fields = k.getDeclaredFields(); List superFields = new ArrayList<>(); Class currentClass = k.getSuperclass(); while (currentClass != null) { Field[] declaredFields = currentClass.getDeclaredFields(); Collections.addAll(superFields, declaredFields); currentClass = currentClass.getSuperclass(); } /* 排除重载属性 */ Map fieldMap = excludeOverrideSuperField(fields, superFields); /* * 重写父类属性过滤后处理忽略部分,支持过滤父类属性功能 * 场景:中间表不需要记录创建时间,忽略父类 createTime 公共属性 * 中间表实体重写父类属性 ` private transient Date createTime; ` */ return fieldMap.values().stream() /* 过滤静态属性 */ .filter(f -> !Modifier.isStatic(f.getModifiers())) /* 过滤 transient关键字修饰的属性 */ .filter(f -> !Modifier.isTransient(f.getModifiers())) .collect(Collectors.toList()); }); } /** *

* 排序重置父类属性 *

* * @param fields 子类属性 * @param superFieldList 父类属性 */ public static Map excludeOverrideSuperField(Field[] fields, List superFieldList) { // 子类属性 Map fieldMap = Stream.of(fields).collect(toMap(Field::getName, identity(), (u, v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); }, LinkedHashMap::new)); superFieldList.stream().filter(field -> !fieldMap.containsKey(field.getName())) .forEach(f -> fieldMap.put(f.getName(), f)); return fieldMap; } /** * 判断是否为基本类型或基本包装类型 * * @param clazz class * @return 是否基本类型或基本包装类型 */ public static boolean isPrimitiveOrWrapper(Class clazz) { Assert.notNull(clazz, "Class must not be null"); return (clazz.isPrimitive() || PRIMITIVE_WRAPPER_TYPE_MAP.containsKey(clazz)); } public static Class resolvePrimitiveIfNecessary(Class clazz) { return (clazz.isPrimitive() && clazz != void.class ? PRIMITIVE_TYPE_TO_WRAPPER_MAP.get(clazz) : clazz); } }