|
@@ -1,17 +1,24 @@
|
|
|
package org.hswebframework.web.boost.bean;
|
|
|
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
+import lombok.Getter;
|
|
|
+import lombok.Setter;
|
|
|
import org.apache.commons.beanutils.BeanUtilsBean;
|
|
|
import org.apache.commons.beanutils.PropertyUtilsBean;
|
|
|
import org.hswebframework.web.boost.Compiler;
|
|
|
import org.springframework.util.ClassUtils;
|
|
|
|
|
|
+import java.beans.BeanDescriptor;
|
|
|
import java.beans.FeatureDescriptor;
|
|
|
import java.beans.PropertyDescriptor;
|
|
|
import java.lang.reflect.Method;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.concurrent.ConcurrentMap;
|
|
|
+import java.util.function.BiFunction;
|
|
|
+import java.util.function.Consumer;
|
|
|
import java.util.function.Function;
|
|
|
+import java.util.function.Supplier;
|
|
|
import java.util.stream.Collectors;
|
|
|
import java.util.stream.Stream;
|
|
|
|
|
@@ -20,9 +27,7 @@ import java.util.stream.Stream;
|
|
|
* @since 3.0
|
|
|
*/
|
|
|
public class FastBeanCopier {
|
|
|
- private static final Map<String, Copier> CACHE = new HashMap<>();
|
|
|
-
|
|
|
- private static final Map<String, Map<String, String>> PROPERTY_MAPPING = new HashMap<>();
|
|
|
+ private static final Map<CacheKey, Copier> CACHE = new HashMap<>();
|
|
|
|
|
|
private static final PropertyUtilsBean propertyUtils = BeanUtilsBean.getInstance().getPropertyUtils();
|
|
|
|
|
@@ -41,14 +46,26 @@ public class FastBeanCopier {
|
|
|
wrapperClassMapping.put(long.class, Long.class);
|
|
|
}
|
|
|
|
|
|
- public static void copy(Object source, Object target, String... ignore) {
|
|
|
- copy(source, target, DEFAULT_CONVERT, ignore);
|
|
|
+ public static <T, S> T copy(S source, T target, String... ignore) {
|
|
|
+ return copy(source, target, DEFAULT_CONVERT, ignore);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <T, S> T copy(S source, Supplier<T> target, String... ignore) {
|
|
|
+ return copy(source, target.get(), DEFAULT_CONVERT, ignore);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <T, S> T copy(S source, Class<T> target, String... ignore) {
|
|
|
+ try {
|
|
|
+ return copy(source, target.newInstance(), DEFAULT_CONVERT, ignore);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException(e.getMessage(), e);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public static Copier getCopier(Object source, Object target, boolean autoCreate) {
|
|
|
Class sourceType = ClassUtils.getUserClass(source);
|
|
|
Class targetType = ClassUtils.getUserClass(target);
|
|
|
- String key = createCacheKey(sourceType, targetType);
|
|
|
+ CacheKey key = createCacheKey(sourceType, targetType);
|
|
|
if (autoCreate) {
|
|
|
return CACHE.computeIfAbsent(key, k -> createCopier(sourceType, targetType));
|
|
|
} else {
|
|
@@ -57,83 +74,165 @@ public class FastBeanCopier {
|
|
|
|
|
|
}
|
|
|
|
|
|
- public static void copy(Object source, Object target, Converter converter, String... ignore) {
|
|
|
+ public static <T, S> T copy(S source, T target, Converter converter, String... ignore) {
|
|
|
+ if (source instanceof Map && target instanceof Map) {
|
|
|
+ ((Map) target).putAll(((Map) source));
|
|
|
+ return target;
|
|
|
+ }
|
|
|
getCopier(source, target, true)
|
|
|
.copy(source, target, (ignore == null || ignore.length == 0) ? new HashSet<>() : new HashSet<>(Arrays.asList(ignore)), converter);
|
|
|
+ return target;
|
|
|
}
|
|
|
|
|
|
- private static String createCacheKey(Class source, Class target) {
|
|
|
- return source.getName().concat("=>").concat(target.getName());
|
|
|
+ private static CacheKey createCacheKey(Class source, Class target) {
|
|
|
+ return new CacheKey(source, target);
|
|
|
}
|
|
|
|
|
|
public static Copier createCopier(Class source, Class target) {
|
|
|
String method = "public void copy(Object s, Object t, java.util.Set ignore, " +
|
|
|
"org.hswebframework.web.boost.bean.Converter converter){\n" +
|
|
|
- source.getName() + " source=(" + source.getName() + ")s;\n" +
|
|
|
- target.getName() + " target=(" + target.getName() + ")t;\n" +
|
|
|
+ "try{\n\t" +
|
|
|
+ source.getName() + " source=(" + source.getName() + ")s;\n\t" +
|
|
|
+ target.getName() + " target=(" + target.getName() + ")t;\n\t" +
|
|
|
createCopierCode(source, target) +
|
|
|
+ "}catch(Exception e){\n" +
|
|
|
+ "\tthrow new RuntimeException(e.getMessage(),e);" +
|
|
|
+ "\n}\n" +
|
|
|
"\n}";
|
|
|
- System.out.println(method);
|
|
|
return Compiler.create(Copier.class)
|
|
|
.addMethod(method)
|
|
|
.newInstance();
|
|
|
}
|
|
|
|
|
|
- private static String createFieldCopierCode(PropertyDescriptor source, PropertyDescriptor target) {
|
|
|
- Method sourceRead = source.getReadMethod();
|
|
|
- if (sourceRead == null) {
|
|
|
- //源对象的get方法不存在
|
|
|
- return "";
|
|
|
- }
|
|
|
- Method targetWrite = target.getWriteMethod();
|
|
|
- if (targetWrite == null) {
|
|
|
- return "";
|
|
|
- }
|
|
|
+ private static Map<String, ClassProperty> createProperty(Class type) {
|
|
|
+ return Stream.of(propertyUtils.getPropertyDescriptors(type))
|
|
|
+ .filter(property -> !property.getName().equals("class") && property.getReadMethod() != null && property.getWriteMethod() != null)
|
|
|
+ .map(BeanClassProperty::new)
|
|
|
+ .collect(Collectors.toMap(ClassProperty::getName, Function.identity()));
|
|
|
|
|
|
- PropertyCopierGenerator generator = new PropertyCopierGenerator();
|
|
|
- generator.target = target;
|
|
|
- generator.source = source;
|
|
|
+ }
|
|
|
|
|
|
- return generator.generate();
|
|
|
+ private static Map<String, ClassProperty> createMapProperty(Map<String, ClassProperty> template) {
|
|
|
+ return template.values().stream().map(classProperty -> new MapClassProperty(classProperty.name))
|
|
|
+ .collect(Collectors.toMap(ClassProperty::getName, Function.identity()));
|
|
|
}
|
|
|
|
|
|
private static String createCopierCode(Class source, Class target) {
|
|
|
- Map<String, PropertyDescriptor> sourceCache = Stream.of(propertyUtils.getPropertyDescriptors(source))
|
|
|
- .collect(Collectors.toMap(FeatureDescriptor::getName, Function.identity()));
|
|
|
- StringBuilder builder = new StringBuilder();
|
|
|
-
|
|
|
- Arrays.asList(propertyUtils.getPropertyDescriptors(target))
|
|
|
- .forEach((targetField) -> {
|
|
|
- PropertyDescriptor sourceField = sourceCache.get(targetField.getName());
|
|
|
- if (null != sourceField) {
|
|
|
- builder.append(createFieldCopierCode(sourceField, targetField))
|
|
|
- .append("\n");
|
|
|
- } else {
|
|
|
- //源字段不存
|
|
|
- }
|
|
|
- });
|
|
|
+ Map<String, ClassProperty> sourceProperties = null;
|
|
|
+
|
|
|
+ Map<String, ClassProperty> targetProperties = null;
|
|
|
+
|
|
|
+ //源类型为Map
|
|
|
+ if (Map.class.isAssignableFrom(source)) {
|
|
|
+ if (!Map.class.isAssignableFrom(target)) {
|
|
|
+ sourceProperties = createProperty(source);
|
|
|
+ targetProperties = createMapProperty(sourceProperties);
|
|
|
+ }
|
|
|
+ } else if (Map.class.isAssignableFrom(target)) {
|
|
|
+ if (!Map.class.isAssignableFrom(source)) {
|
|
|
+ sourceProperties = createProperty(source);
|
|
|
+ targetProperties = createMapProperty(sourceProperties);
|
|
|
+
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ targetProperties = createProperty(target);
|
|
|
+ sourceProperties = createProperty(source);
|
|
|
+ }
|
|
|
+ if (sourceProperties == null || targetProperties == null) {
|
|
|
+ throw new UnsupportedOperationException("不支持的类型,source:" + source + " target:" + target);
|
|
|
+ }
|
|
|
+ StringBuilder code = new StringBuilder();
|
|
|
|
|
|
- return builder.toString();
|
|
|
+ for (ClassProperty sourceProperty : sourceProperties.values()) {
|
|
|
+ ClassProperty targetProperty = targetProperties.get(sourceProperty.getName());
|
|
|
+ if (targetProperty == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ code.append("if(!ignore.contains(\"").append(sourceProperty.getName()).append("\")){\n\t")
|
|
|
+ .append(targetProperty.generateVar(targetProperty.getName())).append("=").append(sourceProperty.generateGetter(targetProperty.getType()))
|
|
|
+ .append(";\n");
|
|
|
+ if (!sourceProperty.isPrimitive()) {
|
|
|
+ code.append("\tif(").append(sourceProperty.getName()).append("!=null){\n");
|
|
|
+ }
|
|
|
+ code.append("\ttarget.").append(targetProperty.generateSetter(targetProperty.getType(), sourceProperty.getName())).append(";\n");
|
|
|
+ if (!sourceProperty.isPrimitive()) {
|
|
|
+ code.append("\t}\n");
|
|
|
+ }
|
|
|
+ code.append("}\n");
|
|
|
+ }
|
|
|
+//
|
|
|
+// Map<String, PropertyDescriptor> sourceCache = Stream.of(propertyUtils.getPropertyDescriptors(source))
|
|
|
+// .collect(Collectors.toMap(FeatureDescriptor::getName, Function.identity()));
|
|
|
+// StringBuilder builder = new StringBuilder();
|
|
|
+//
|
|
|
+// Arrays.asList(propertyUtils.getPropertyDescriptors(target))
|
|
|
+// .forEach((targetField) -> {
|
|
|
+// PropertyDescriptor sourceField = sourceCache.get(targetField.getName());
|
|
|
+// if (null != sourceField) {
|
|
|
+// builder.append(createFieldCopierCode(sourceField, targetField))
|
|
|
+// .append("\n");
|
|
|
+// } else {
|
|
|
+// //源字段不存在
|
|
|
+// }
|
|
|
+// });
|
|
|
+
|
|
|
+ return code.toString();
|
|
|
}
|
|
|
|
|
|
- static class PropertyCopierGenerator {
|
|
|
- PropertyDescriptor source;
|
|
|
- PropertyDescriptor target;
|
|
|
- List<String> lines = new ArrayList<>();
|
|
|
+ static abstract class ClassProperty {
|
|
|
+
|
|
|
+ @Getter
|
|
|
+ protected String name;
|
|
|
+
|
|
|
+ @Getter
|
|
|
+ protected String readMethodName;
|
|
|
+
|
|
|
+ @Getter
|
|
|
+ protected String writeMethodName;
|
|
|
+
|
|
|
+ @Getter
|
|
|
+ protected Function<Class, String> getter;
|
|
|
+
|
|
|
+ @Getter
|
|
|
+ protected BiFunction<Class, String, String> setter;
|
|
|
+
|
|
|
+ @Getter
|
|
|
+ protected Class type;
|
|
|
|
|
|
- private boolean targetIsPrimitive() {
|
|
|
- return target.getPropertyType().isPrimitive();
|
|
|
+ public String getReadMethod() {
|
|
|
+ return readMethodName + "()";
|
|
|
}
|
|
|
|
|
|
- private boolean sourceIsPrimitive() {
|
|
|
- return source.getPropertyType().isPrimitive();
|
|
|
+ public String generateVar(String name) {
|
|
|
+ return getTypeName().concat(" ").concat(name);
|
|
|
}
|
|
|
|
|
|
- private boolean typeIsWrapper(Class type) {
|
|
|
+ public String getTypeName() {
|
|
|
+ String targetTypeName = type.getName();
|
|
|
+ if (type.isArray()) {
|
|
|
+ targetTypeName = type.getComponentType().getName() + "[]";
|
|
|
+ }
|
|
|
+ return targetTypeName;
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean isPrimitive() {
|
|
|
+ return isPrimitive(getType());
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean isPrimitive(Class type) {
|
|
|
+ return type.isPrimitive();
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean isWrapper() {
|
|
|
+ return isWrapper(getType());
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean isWrapper(Class type) {
|
|
|
return wrapperClassMapping.values().contains(type);
|
|
|
}
|
|
|
|
|
|
- private Class getPrimitiveType(Class type) {
|
|
|
+ protected Class getPrimitiveType(Class type) {
|
|
|
return wrapperClassMapping.entrySet().stream()
|
|
|
.filter(entry -> entry.getValue() == type)
|
|
|
.map(Map.Entry::getKey)
|
|
@@ -141,100 +240,134 @@ public class FastBeanCopier {
|
|
|
.orElse(null);
|
|
|
}
|
|
|
|
|
|
- private String getReadSourceObjectValueCode() {
|
|
|
- if (sourceIsPrimitive()) {
|
|
|
- Class wrapperClass = wrapperClassMapping.get(source.getPropertyType());
|
|
|
- return wrapperClass.getName() + ".valueOf(source." + source.getReadMethod().getName() + "())";
|
|
|
- }
|
|
|
-
|
|
|
- return "source." + source.getReadMethod().getName() + "()";
|
|
|
+ protected Class getWrapperType() {
|
|
|
+ return wrapperClassMapping.get(type);
|
|
|
}
|
|
|
|
|
|
- private boolean notNull() {
|
|
|
- return !sourceIsPrimitive();
|
|
|
+ protected String castWrapper(String getter) {
|
|
|
+ return getWrapperType().getSimpleName().concat(".valueOf(").concat(getter).concat(")");
|
|
|
}
|
|
|
|
|
|
- private void generateConvert() {
|
|
|
- StringBuilder convertCode = new StringBuilder();
|
|
|
- convertCode.append("if(!ignore.contains(\"").append(target.getName())
|
|
|
- .append("\")");
|
|
|
- if (notNull()) {
|
|
|
- convertCode.append("&&source.")
|
|
|
- .append(source.getReadMethod().getName())
|
|
|
- .append("()!=null");
|
|
|
- }
|
|
|
- String targetTypeName = target.getPropertyType().getName();
|
|
|
- if (target.getPropertyType().isArray()) {
|
|
|
- targetTypeName = target.getPropertyType().getComponentType().getName() + "[]";
|
|
|
- }
|
|
|
- convertCode.append("){\n");
|
|
|
- convertCode.append(targetTypeName)
|
|
|
- .append(" ")
|
|
|
- .append(target.getName()).append("=");
|
|
|
- String convert = "converter.convert((Object)(" + getReadSourceObjectValueCode() + "),"
|
|
|
- + target.getPropertyType().getName() + ".class)";
|
|
|
- if (source.getPropertyType() != target.getPropertyType()) {
|
|
|
- if (targetIsPrimitive()) {
|
|
|
- boolean sourceIsWrapper = typeIsWrapper(source.getPropertyType());
|
|
|
- Class targetWrapperClass = wrapperClassMapping.get(target.getPropertyType());
|
|
|
-
|
|
|
- Class sourcePrimitive = getPrimitiveType(source.getPropertyType());
|
|
|
- if (sourceIsWrapper) {
|
|
|
- convertCode.append(target.getPropertyType().getName())
|
|
|
- .append(".valueOf(")
|
|
|
- .append(getReadSourceObjectValueCode())
|
|
|
- .append(".")
|
|
|
- .append(sourcePrimitive.getName())
|
|
|
- .append("Value());");
|
|
|
- } else {
|
|
|
- convertCode.append("((").append(targetWrapperClass.getName())
|
|
|
- .append(")")
|
|
|
- .append(convert)
|
|
|
- .append(").")
|
|
|
-// .append(target.getPropertyType().getName())
|
|
|
-// .append("Value()).")
|
|
|
- .append(target.getPropertyType().getName())
|
|
|
- .append("Value();");
|
|
|
- }
|
|
|
-// convertCode.append(getReadSourceObjectValueCode())
|
|
|
-// .append(".")
|
|
|
-// .append(target.getPropertyType().getName()).append("Value();");
|
|
|
-
|
|
|
- } else if (sourceIsPrimitive()) {
|
|
|
- boolean targetIsWrapper = typeIsWrapper(target.getPropertyType());
|
|
|
- Class targetPrimitive = getPrimitiveType(target.getPropertyType());
|
|
|
- if (targetIsWrapper) {
|
|
|
- convertCode.append(target.getPropertyType().getName())
|
|
|
- .append(".valueOf(")
|
|
|
- .append(getReadSourceObjectValueCode())
|
|
|
- .append(".")
|
|
|
- .append(targetPrimitive.getName())
|
|
|
- .append("Value());");
|
|
|
+ public Function<Class, String> createGetterFunction() {
|
|
|
+
|
|
|
+ return (targetType) -> {
|
|
|
+ String getterCode = "source." + getReadMethod();
|
|
|
+
|
|
|
+ String convert = "converter.convert((Object)(" + (isPrimitive() ? castWrapper(getterCode) : getterCode) + "),"
|
|
|
+ + targetType.getName() + ".class)";
|
|
|
+ StringBuilder convertCode = new StringBuilder();
|
|
|
+
|
|
|
+ if (targetType != getType()) {
|
|
|
+ if (isPrimitive(targetType)) {
|
|
|
+ boolean sourceIsWrapper = isWrapper(getType());
|
|
|
+ Class targetWrapperClass = wrapperClassMapping.get(targetType);
|
|
|
+
|
|
|
+ Class sourcePrimitive = getPrimitiveType(getType());
|
|
|
+ //目标字段是基本数据类型,源字段是包装器类型
|
|
|
+ // Integer.valueOf(source.getField()).intValue();
|
|
|
+ if (sourceIsWrapper) {
|
|
|
+ convertCode.append(targetType.getName())
|
|
|
+ .append(".valueOf(")
|
|
|
+ .append(getterCode)
|
|
|
+ .append(".")
|
|
|
+ .append(sourcePrimitive.getName())
|
|
|
+ .append("Value())");
|
|
|
+ } else {
|
|
|
+ //类型不一致,调用convert转换
|
|
|
+ convertCode.append("((").append(targetWrapperClass.getName())
|
|
|
+ .append(")")
|
|
|
+ .append(convert)
|
|
|
+ .append(").")
|
|
|
+ .append(targetType.getName())
|
|
|
+ .append("Value()");
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if (isPrimitive()) {
|
|
|
+ boolean targetIsWrapper = isWrapper(targetType);
|
|
|
+ //源字段类型为基本数据类型,目标字段为包装器类型
|
|
|
+ if (targetIsWrapper) {
|
|
|
+ Class targetPrimitive = getPrimitiveType(targetType);
|
|
|
+ convertCode.append(targetType.getName())
|
|
|
+ .append(".valueOf(")
|
|
|
+ .append(getterCode)
|
|
|
+ .append(".")
|
|
|
+ .append(targetPrimitive.getName())
|
|
|
+ .append("Value())");
|
|
|
+ } else {
|
|
|
+ convertCode.append("(").append(targetType.getName())
|
|
|
+ .append(")(")
|
|
|
+ .append(convert)
|
|
|
+ .append(")");
|
|
|
+ }
|
|
|
} else {
|
|
|
- convertCode.append("(").append(target.getPropertyType().getName())
|
|
|
+ convertCode.append("(").append(targetType.getName())
|
|
|
.append(")(")
|
|
|
.append(convert)
|
|
|
- .append(");");
|
|
|
+ .append(")");
|
|
|
}
|
|
|
} else {
|
|
|
- convertCode.append("(").append(target.getPropertyType().getName())
|
|
|
- .append(")(")
|
|
|
- .append(convert)
|
|
|
- .append(");");
|
|
|
+
|
|
|
+ if (Cloneable.class.isAssignableFrom(targetType)) {
|
|
|
+ try {
|
|
|
+ targetType.getMethod("clone");
|
|
|
+ convertCode.append("(" + getTypeName() + ")").append(getterCode).append(".clone();");
|
|
|
+ } catch (NoSuchMethodException e) {
|
|
|
+ convertCode.append(getterCode);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ convertCode.append(getterCode);
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
- } else {
|
|
|
- convertCode.append("source.")
|
|
|
- .append(source.getReadMethod().getName())
|
|
|
- .append("();");
|
|
|
- }
|
|
|
- convertCode.append("\ntarget.").append(target.getWriteMethod().getName()).append("(").append(target.getName()).append(");");
|
|
|
- convertCode.append("\n}");
|
|
|
- lines.add(convertCode.toString());
|
|
|
+// if (!isPrimitive()) {
|
|
|
+// return getterCode + "!=null?" + convertCode.toString() + ":null";
|
|
|
+// }
|
|
|
+ return convertCode.toString();
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ public BiFunction<Class, String, String> createSetterFunction(Function<String, String> settingNameSupplier) {
|
|
|
+ return (sourceType, paramGetter) -> {
|
|
|
+
|
|
|
+ return settingNameSupplier.apply(paramGetter);
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ public String generateGetter(Class targetType) {
|
|
|
+ return getGetter().apply(targetType);
|
|
|
+ }
|
|
|
+
|
|
|
+ public String generateSetter(Class targetType, String getter) {
|
|
|
+ return getSetter().apply(targetType, getter);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ static class BeanClassProperty extends ClassProperty {
|
|
|
+ public BeanClassProperty(PropertyDescriptor descriptor) {
|
|
|
+ type = descriptor.getPropertyType();
|
|
|
+ readMethodName = descriptor.getReadMethod().getName();
|
|
|
+ writeMethodName = descriptor.getWriteMethod().getName();
|
|
|
+
|
|
|
+ getter = createGetterFunction();
|
|
|
+ setter = createSetterFunction(paramGetter -> writeMethodName + "(" + paramGetter + ")");
|
|
|
+ name = descriptor.getName();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ static class MapClassProperty extends ClassProperty {
|
|
|
+ public MapClassProperty(String name) {
|
|
|
+ type = Object.class;
|
|
|
+ this.name = name;
|
|
|
+ this.readMethodName = "get";
|
|
|
+ this.writeMethodName = "put";
|
|
|
+
|
|
|
+ this.getter = createGetterFunction();
|
|
|
+ this.setter = createSetterFunction(paramGetter -> "put(\"" + name + "\"," + paramGetter + ")");
|
|
|
}
|
|
|
|
|
|
- public String generate() {
|
|
|
- generateConvert();
|
|
|
- return String.join("\n", lines.toArray(new String[lines.size()]));
|
|
|
+ @Override
|
|
|
+ public String getReadMethodName() {
|
|
|
+ return "get(\"" + name + "\")";
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -248,7 +381,9 @@ public class FastBeanCopier {
|
|
|
if (targetClass == String.class) {
|
|
|
return (T) String.valueOf(source);
|
|
|
}
|
|
|
-
|
|
|
+ if (targetClass == Object.class) {
|
|
|
+ return (T) source;
|
|
|
+ }
|
|
|
org.apache.commons.beanutils.Converter converter = BeanUtilsBean
|
|
|
.getInstance()
|
|
|
.getConvertUtils()
|
|
@@ -261,9 +396,33 @@ public class FastBeanCopier {
|
|
|
copy(source, newTarget);
|
|
|
return newTarget;
|
|
|
} catch (Exception e) {
|
|
|
+
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ @AllArgsConstructor
|
|
|
+ public static class CacheKey {
|
|
|
+
|
|
|
+ private Class targetType;
|
|
|
+
|
|
|
+ private Class sourceType;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object obj) {
|
|
|
+ if (!(obj instanceof CacheKey)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ CacheKey target = ((CacheKey) obj);
|
|
|
+ return target.targetType == targetType && target.sourceType == sourceType;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int hashCode() {
|
|
|
+ int result = this.targetType != null ? this.targetType.hashCode() : 0;
|
|
|
+ result = 31 * result + (this.sourceType != null ? this.sourceType.hashCode() : 0);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|