目的
我想要实现两个任意类型之间的值以及Field字段之间的赋值,不仅仅只是简单的同类赋值,而是可以通过间接转换来进行实现值之间的赋值。例如你完全知道"1" 和 1可以相互转换赋值。{1,2,3,4,5} 和 [1,2,3,4,5] 和 {"1","2","3","4","5"}, "1,2,3,4,5" 等等之间其实是可以相互赋值转换的。数值类型和包装类型,字符串类型和任意类型。数组类型和集合类型。 下面是我的屎山代码实现链接:github.com/HK-hub/h-tr… 具体的类在这里:屎山代码
实现
DynamicValueHelper 类 和ReflectUtil 类:
package com.hk.transformation.core.helper;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.hk.transformation.core.annotation.dynamic.DynamicSwitch;
import com.hk.transformation.core.annotation.dynamic.DynamicValue;
import com.hk.transformation.core.constants.TransformationConstants;
import com.hk.transformation.core.reflect.converter.CollectionConverter;
import com.hk.transformation.core.reflect.converter.StringConverter;
import com.hk.transformation.core.reflect.util.ReflectUtil;
import com.hk.transformation.core.value.DynamicValueBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.*;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.core.annotation.AnnotationUtils;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.*;
/**
* @author : HK意境
* @ClassName : DynamicValueHelper
* @date : 2023/7/31 17:20
* @description :
* @Todo :
* @Bug :
* @Modified :
* @Version : 1.0
*/
@Slf4j
public class DynamicValueHelper {
/**
* 计算Field字段的@DynamicValue 注解出来
* @param bean
* @param field
* @return
*/
public static DynamicValueBean computeDynamicFieldAnnotation(Object bean, Field field) {
// 判断是否直接标注@DynamicValue 注解,还是@DynamicSwitch 注解,还是通过在Class类上标注的@DynamicValue
DynamicValueBean dynamicValueBean = new DynamicValueBean();
// 获取Field字段上的@DynamicValue注解
DynamicValue dynamicValue = AnnotationUtils.getAnnotation(field, DynamicValue.class);
if (Objects.nonNull(dynamicValue)) {
// 获取Key: 因为使用了@AliasFor 注解和 key() 属性是相通的
String key = (String) AnnotationUtils.getValue(dynamicValue);
if (StringUtils.isBlank(key)) {
// key 是默认值或者空的, 采用字段的全限定名称
String clazzName = field.getDeclaringClass().getName();
String fieldName = field.getName();
key = clazzName + TransformationConstants.FIELD_LOCATION_SEPARATOR + fieldName;
}
// 获取默认值: 如果注解没有配置默认值,那么设置
String value = dynamicValue.defaultValue();
if (Objects.isNull(value) || value.length() == 0) {
// 如果是默认值"", 则需要进行判断
try {
// 获取field字段声明的时候的初始值
field.setAccessible(true);
Object initValue = field.get(bean);
if (Objects.nonNull(initValue)) {
// 非空,进行赋值
value = ReflectUtil.valueToAdaptiveString(initValue);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
// 获取值类型的Class
Class<?> valueClass = dynamicValue.valueClass();
if (Objects.isNull(valueClass) || ReflectUtil.isVoidType(valueClass)) {
// 如果没有指定类型或者类型为void -> 获取Field字段类型进行赋值
valueClass = field.getType();
}
// 获取规则表达式
String expression = dynamicValue.expression();
if (StringUtils.isNotBlank(expression)) {
String elType = dynamicValue.elType();
dynamicValueBean.setExpression(expression).setElType(elType);
}
// 构造DynamicValueBean 对象
dynamicValueBean.setKey(key).setValue(value).setDefaultValue(value).setValueClass(valueClass);
return dynamicValueBean;
}
// @DynamicValue 注解为空,判断是否为添加了@DynamicSwitch 注解
DynamicSwitch dynamicSwitch = AnnotationUtils.getAnnotation(field, DynamicSwitch.class);
if (Objects.nonNull(dynamicSwitch)) {
// 获取Key: 因为使用了@AliasFor 注解和 key() 属性是相通的
String key = (String) AnnotationUtils.getValue(dynamicSwitch);
if (StringUtils.isBlank(key)) {
// key 是默认值或者空的, 采用字段的全限定名称
String clazzName = field.getDeclaringClass().getName();
String fieldName = field.getName();
key = clazzName + TransformationConstants.FIELD_LOCATION_SEPARATOR + fieldName;
}
// 获取默认值: 如果注解没有配置默认值,那么设置
boolean value = dynamicSwitch.defaultValue();
if (BooleanUtils.isFalse(value)) {
// 如果是默认值false, 则需要进行判断
try {
// 获取field字段声明的时候的初始值
field.setAccessible(true);
boolean initValue = field.getBoolean(bean);
if (Objects.nonNull(initValue)) {
// 非空,进行赋值
value = initValue;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
// 获取值类型的Class
Class<?> valueClass = dynamicSwitch.valueClass();
if (Objects.isNull(valueClass) || ReflectUtil.isVoidType(valueClass)) {
// 如果没有指定类型或者类型为void -> 获取Field字段类型进行赋值
valueClass = field.getType();
}
// 获取规则表达式
String expression = dynamicSwitch.expression();
if (StringUtils.isNotBlank(expression)) {
String elType = dynamicSwitch.elType();
dynamicValueBean.setExpression(expression).setElType(elType);
}
// 构造DynamicValueBean 对象
String initValue = Boolean.valueOf(value).toString();
dynamicValueBean.setKey(key).setValue(initValue)
.setDefaultValue(initValue)
.setValueClass(valueClass);
return dynamicValueBean;
}
// 如果这些注解都没有,需要判断类上是否添加了@DynamicValue 注解来进行设置
dynamicValue = AnnotationUtils.findAnnotation(bean.getClass(), DynamicValue.class);
if (Objects.nonNull(dynamicValue)) {
// 此处是添加在类上的动态注解
// TODO 后期考虑添加缓存存储这些注解信息,与对象,field,method的映射信息
// key 为field 的全限定名称,或者如果类上的DynamicValue 注解指定了key 则采用key.fieldName
String key = dynamicValue.key();
if (StringUtils.isEmpty(key) || key.length() == 0) {
key = bean.getClass().getName();
}
key = key.concat(TransformationConstants.FIELD_LOCATION_SEPARATOR).concat(field.getName());
// 默认值:field 字段的显示初始值
Object initValue = null;
Class<?> initValueClass = null;
try {
initValue = field.get(bean);
initValueClass = initValue.getClass();
// 设置
dynamicValueBean.setValue(initValue.toString())
.setDefaultValue(initValue.toString())
.setValueClass(initValueClass);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// TODO 考虑String 类型更改为Object类型
// TODO 以后考虑字段上的@Value注解内部的 spEl 表达式
dynamicValueBean.setKey(key);
return dynamicValueBean;
}
// 能够寻找的地方都进行了查找,还是不能构建出来,返回null, 外面进行判断
return null;
}
/**
* 给字段赋值
* @param field 字段
* @param value 值
* @param clazz 值类型
*/
public static void assignField(Field field, String value, Class<?> clazz) {
Class<?> type = field.getType();
}
/**
* 计算出能够赋值的适配的类,如果不能转换为适配的类,将抛出异常
* @param bean
* @param field 字段属性声明类型
* @param value 原始数值
* @param valueClass
* @return
*/
public static Object computeAdaptiveDynamicValue(Object bean, Field field, Object value, Class<?> valueClass) {
// 判断是否可以分配
boolean assignable = ReflectUtil.isAssignable(field, field.getType(), value, valueClass);
if (BooleanUtils.isFalse(assignable)) {
// 不能赋值
log.error("field:{}-class:{} can not assigned by value:{}-class{}", field, field.getClass(), value, valueClass);
throw new ClassCastException("field:" + field + "-class:"+ field.getClass() + ", can not assigned by value:"+ value + "-class:" + valueClass);
}
Class<?> fieldType = field.getType();
// // 判断 valueClass 是否可以直接分配给 fieldClass
if (ClassUtils.isAssignable(valueClass, fieldType)) {
// 可以直接分配,返回值
return value;
}
// 是否基本类型
if (ReflectUtil.isBaseType(fieldType)) {
// 基本类型:number,void, boolean, char, string
if (ReflectUtil.isNumberType(fieldType)) {
// 如果valueClass 也是number类型那么在前面 ClassUtils.isAssignable() 则会判断成功已经返回了
// 此时value 可能为Number中非基本类型及其包装类,或者为String类
if (valueClass.isPrimitive()) {
// 如果是基本类型需要转换为包装类型
valueClass = ClassUtils.wrapperToPrimitive(valueClass);
}
// 判断是否是数值类型
if (ReflectUtil.isNumberType(valueClass)) {
return NumberUtils.createNumber(value.toString());
} else if (ReflectUtil.isStringType(valueClass)) {
// 如果是String 直接尝试转换为Number
return NumberUtils.createNumber(value.toString());
}
// 如果既不是基本数值类型也不是其包装类型,也不是字符串那么无法转换,抛出异常
throw new ClassCastException("value:" + value + ", class is " + valueClass + ", can not convert to field class:" + fieldType);
} else if (ReflectUtil.isBooleanType(fieldType)) {
// boolean 类型: 直接判断是否可以转为Boolean
return BooleanUtils.toBooleanObject(value.toString());
} else if (ReflectUtil.isCharType(fieldType)) {
// char 类型,尝试直接转换为一个char
if (ReflectUtil.isCharType(valueClass)) {
// 无需转换直接返回
return value;
}
// 转换成为char
return CharUtils.toCharacterObject(value.toString());
} else if (ReflectUtil.isStringType(valueClass)) {
return String.valueOf(value);
}
}
// 是否集合类型
else if (ReflectUtil.isCollectionType(fieldType)) {
Class<?> genericType = ReflectUtil.getGenericType(field);
// 如果是集合类型可以判断value 是否集合,还是componentClass ,还是String 类型来进行单独值转换
if (ReflectUtil.isCollectionType(valueClass)) {
return CollectionConverter.convertCollection(fieldType, (Collection) value, genericType);
} else if (genericType.isAssignableFrom(valueClass)) {
// 如果不是集合,判断泛型类型是否可以被value类型赋值
return value;
} else if (ReflectUtil.isPrimitiveOrWrapperType(valueClass)) {
// 如果是基本数据类型
return genericType.cast(value);
} else if (ReflectUtil.isStringType(valueClass)) {
// String 类型的需要将其转换为[], 或者{} 格式
String[] valueArray = StringConverter.convertStringToArray(String.valueOf(value));
// 还需要判断元素能不能转换为genericType
Gson gson = new Gson();
ArrayList<Object> res = Lists.newArrayList();
for (String v : valueArray) {
res.add(gson.fromJson(v, genericType));
}
return res;
} else {
throw new ClassCastException("value:" + value + ", class is " + valueClass + ", can not convert to field class:" + fieldType);
}
}
// 是数组类型
else if (ReflectUtil.isArrayType(fieldType)) {
// 获取componentType
Class<?> componentType = fieldType.getComponentType();
// 如果value 也是Array类型
if (ReflectUtil.isArrayType(valueClass)) {
Class<?> valueComponentType = valueClass.getComponentType();
if (ClassUtils.isAssignable(valueComponentType, componentType)) {
// 可以直接赋值
return value;
} else {
// 类型不能直接赋值,是否可以通过转换
Gson gson = new Gson();
gson.fromJson(String.valueOf(value), fieldType);
}
} else if (ReflectUtil.isPrimitiveOrWrapperType(valueClass)) {
if (ClassUtils.isAssignable(valueClass, componentType)) {
return value;
}
throw new ClassCastException("value:" + value + ", class is " + valueClass + ", can not convert to field class:" + fieldType);
} else if (ReflectUtil.isStringType(valueClass)) {
// 转换为数组分割
String[] vArray = StringConverter.convertStringToArray((String) value);
// 创建ComponentType 类型数组
Gson gson = new Gson();
Object componentArray = Array.newInstance(componentType, vArray.length);
// 添加转换后的元素
for (int i = 0; i < vArray.length; i++) {
// 转换元素为指定类型
Object o = gson.fromJson(vArray[i], componentType);
// 如果可以成功转换,设置,没有抛出异常则说明能够构造出适应的数据结构
Array.set(componentArray, i, o);
}
// 没有抛出异常
return componentArray;
} else if (ReflectUtil.isCollectionType(valueClass)) {
// 集合类型: 直接判断是否可以转换
Type valueGenericType = ReflectUtil.getGenericType(valueClass);
if (ClassUtils.isAssignable((Class<?>) valueGenericType, fieldType)) {
return ((Collection) value).toArray();
}
}
}
// 是否Map 类型
else if (ReflectUtil.isMapType(fieldType)) {
}
// 是否对象类型
else {
Gson gson = new Gson();
return gson.fromJson((String) value, fieldType);
}
// 战时没有匹配的类型
throw new ClassCastException("value:" + value + ", class is " + valueClass + ", can not convert to field class:" + fieldType);
}
}
ReflectUtil 工具类:
package com.hk.transformation.core.reflect.util;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;
/**
* @author : HK意境
* @ClassName : ReflectUtil
* @date : 2023/8/19 10:27
* @description :
* @Todo :
* @Bug :
* @Modified :
* @Version : 1.0
*/
public class ReflectUtil {
/**
* 判断是否可以赋值
* @param field 字段
* @param value
* @param fieldType 字段属性声明类型
* @param valueType
* @return
*/
public static boolean isAssignable(Field field, Class<?> fieldType, Object value, Class<?> valueType) {
// 如果是 void.class 不能赋值
if (isVoidType(fieldType) || isVoidType(valueType)) {
return false;
}
// 如果设置的类型都是相同的那么即可直接赋值
if (fieldType.isAssignableFrom(valueType)) {
// 可赋值的
return true;
}
// 判断field 是否基本类型
if (isBaseType(fieldType)) {
if (isStringType(fieldType)) {
if (isStringType(valueType)) {
return true;
}
// 不是String类型但是如果是基本类型,那么是可以转换为String的,但如果是其他对象类型则不行
return isBaseType(valueType);
} else if (isNumberType(fieldType)) {
// 判断是否数值类型
if (isNumberType(valueType)) {
return true;
} else if (String.class.equals(valueType)) {
// 是字符串,判断是否可以通过转换成为数值
return NumberUtils.isCreatable(String.valueOf(value));
}
} else if (isCharType(fieldType)) {
// 是否Char类型
if (isCharType(valueType)) {
return true;
} else if (String.class.equals(valueType)) {
return isCharValue((String) value);
}
} else if (isBooleanType(fieldType)) {
// 是否Boolean类型
if (isCharType(valueType)) {
return true;
} else if (String.class.equals(valueType)) {
return isBooleanValue((String) value);
}
}
} else if (fieldType.isArray()) {
// 是否数组类型
// 获取数组成员类型
Class<?> fieldComponentType = fieldType.getComponentType();
// 需要判断valueType是否也为数组
if (valueType.isArray()) {
// 如果也是数组需要判断成员是否能够赋值
Class<?> valueComponentType = valueType.getComponentType();
// 如果值类型也是数组对象,其实可以直接判断两个成员类型是否可以赋值
return fieldComponentType.isAssignableFrom(valueComponentType);
} else {
// valueType 值类型不是数组,但是可能为单个元素值,也可能为String
// 判断valueType 和 fieldComponentType 的关系。
if (fieldComponentType.isAssignableFrom(valueType)) {
// 单个元素可以赋值
return true;
}
// 不是能够直接赋值的,需要判断是否可以转换
if (isBaseType(fieldComponentType) && isBaseType(valueType)) {
return true;
}
return false;
}
} else if (isCollectionType(fieldType)) {
// 判断valueType 类型
Class<?> genericType = getGenericType(field);
if (isCollectionType(valueType)) {
// 是否可以赋值或进行转换
return true;
} else if (isStringType(valueType)) {
// 字符串类型
return true;
} else if (isArrayType(valueType)){
// 非集合,非字符串,尝试是否数组类型
// 获取集合元素类型
Class<?> componentType = valueType.getComponentType();
if (genericType.isAssignableFrom(componentType)) {
// 能够直接赋值
return true;
} else if (isBaseType(genericType) && isBaseType(componentType)){
// 不能直接赋值,是否可以通过转换
return true;
} else if (isStringType(componentType)) {
return true;
}
}
return false;
} else {
// 是否对象类型
return isStringType(valueType);
}
return false;
}
/**
* 是否基本类型:原始类型 + 包装类 + 字符串类型
* @param targetClazz
* @return
*/
public static boolean isBaseType(Class<?> targetClazz) {
return isNumberType(targetClazz) || isCharType(targetClazz) || isBooleanType(targetClazz) || isStringType(targetClazz);
}
/**
* 是否基本类型及其包装类,不包括String
* @param targetClazz
* @return
*/
public static boolean isPrimitiveOrWrapperType(Class<?> targetClazz) {
return isNumberType(targetClazz) || isCharType(targetClazz) || isBooleanType(targetClazz);
}
/**
* 是否数组类型
* @param targetClazz
* @return
*/
public static boolean isArrayType(Class<?> targetClazz) {
return targetClazz.isArray();
}
/**
* 是否集合类型
* @param targetClazz
* @return
*/
public static boolean isCollectionType(Class<?> targetClazz) {
return Collection.class.isAssignableFrom(targetClazz);
}
/**
* 是否是Map 类型
* @param targetClazz
* @return
*/
public static boolean isMapType(Class<?> targetClazz) {
return Map.class.isAssignableFrom(targetClazz);
}
/**
* 判断是否数值类型
* @param targetClazz java.lang.reflect.Field 的数据类型 clazz。 getType 方法获取
* @return boolean 是否是Number类型
*/
public static boolean isNumberType(Class<?> targetClazz) {
// 判断包装类
if (Number.class.isAssignableFrom(targetClazz)) {
// 基本类型包装类,BigDecimal, BigInteger, 原子类
return true;
}
// 判断原始类,过滤掉特殊的基本类型
if (targetClazz == boolean.class || targetClazz == char.class || targetClazz == void.class) {
return false;
}
// 基本类型 + boolean + char + void
return targetClazz.isPrimitive();
}
/**
* 判断是否Boolean类型
* @param targetClazz 目标类
* @return
*/
public static boolean isBooleanType(Class<?> targetClazz) {
// Boolean 类型就两种状态基本类和包装类
return Boolean.class.isAssignableFrom(targetClazz);
}
/**
* 判断是否Boolean类型
* @param targetClazz 目标类
* @return
*/
public static boolean isCharType(Class<?> targetClazz) {
// Boolean 类型就两种状态基本类和包装类
return Character.class.isAssignableFrom(targetClazz);
}
/**
* 判断是否String类型
* @param targetClazz
* @return
*/
public static boolean isStringType(Class<?> targetClazz) {
return String.class.equals(targetClazz);
}
/**
* 判断是否void类型
* @param targetClazz
* @return
*/
public static boolean isVoidType(Class<?> targetClazz) {
return Void.class.equals(targetClazz) || void.class.equals(targetClazz);
}
/**
* 判断一个String是否可以转换为Boolean值
* @param value
* @return
*/
public static boolean isBooleanValue(String value) {
return "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
}
/**
* 判断一个String是否可以转换为Char
* @param str
* @return
*/
public static boolean isCharValue(String str) {
return StringUtils.isEmpty(str) || str.length() == 1;
}
/**
* 获取泛型的类型
* @param field
* @return
*/
public static Class<?> getGenericType(Field field) {
Type listFieldType = field.getGenericType();
if (listFieldType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) listFieldType).getActualTypeArguments();
if (actualTypeArguments.length > 0) {
// 显示指定了泛型类型
Type genericType = actualTypeArguments[0];
return getTypeClass(genericType);
} else {
// 没有指定泛型类型,返回 Object
return Object.class;
}
} else {
// 没有指定泛型
return field.getDeclaringClass();
}
}
/**
* 获取一个类声明的泛型参数
* @param clazz
* @return
*/
public static Type getGenericType(Class<?> clazz) {
Type type = clazz.getGenericSuperclass();
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] typeArguments = parameterizedType.getActualTypeArguments();
if (typeArguments.length > 0) {
return typeArguments[0];
}
}
return Object.class;
}
public static Class<?> getTypeClass(Type type) {
if (type instanceof Class) {
return (Class<?>) type;
} else if (type instanceof ParameterizedType) {
return (Class<?>) ((ParameterizedType) type).getRawType();
} else {
throw new IllegalArgumentException("Unsupported Type: " + type);
}
}
/**
* 将Value转换为适合的String:基本类型直接of(), 数组类型转换为[e1,e2,e3,e4], 集合类型转换为{1,2,3,4},对象类型转换为JSON对象,Map 类型转换为{key:value,key:value,key:value}
* @param value
* @return
*/
public static String valueToAdaptiveString(Object value) {
return "";
}
}
求助
各位大佬看了我的代码什么感想,想要求助还有什么更加优雅和好的方法或者开源工具类方案的。迫切需要解决这个核心问题。