Spring BeanCopier深度复制

来源:互联网 发布:js中的li怎么去掉 编辑:程序博客网 时间:2024/04/29 15:41

在Java EE项目中有的时候需要在Bo,Vo,Po之间进行复制,如果类中的属性少的话,我们还可以自己通过最简单的set方式赋值,但如果属性多了,比如一个类中有100个属性,难道你需要一步一步的set吗?那岂不是要疯了?所以,我们需要想着用其他的方式解决这个问题,通过不断地研究,写出了下面的解决方案。


使用Spring 的BeanCopier解决不同类之间的深度复制,下面贴出代码,供大家参考:

1.BeanUtils:

package org.example.common.copier;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;import org.springframework.cglib.beans.BeanCopier;import org.springframework.cglib.core.Converter;public class BeanUtils {/** * the beanCopierMap */private static final ConcurrentMap<String, BeanCopier> beanCopierMap = new ConcurrentHashMap<>();/** * @description 两个类对象之间转换 * @param source * @param target * @return * @return T */public static <T> T convert(Object source, Class<T> target) {T ret = null;if (source != null) {try {ret = target.newInstance();} catch (ReflectiveOperationException e) {throw new RuntimeException("create class[" + target.getName()+ "] instance error", e);}BeanCopier beanCopier = getBeanCopier(source.getClass(), target);beanCopier.copy(source, ret, new DeepCopyConverter(target));}return ret;}public static class DeepCopyConverter implements Converter {/** * The Target. */private Class<?> target;/** * Instantiates a new Deep copy converter. * * @param target *            the target */public DeepCopyConverter(Class<?> target) {this.target = target;}@Overridepublic Object convert(Object value, Class targetClazz, Object methodName) {if (value instanceof List) {List values = (List) value;List retList = new ArrayList<>(values.size());for (final Object source : values) {String tempFieldName = methodName.toString().replace("set","");String fieldName = tempFieldName.substring(0, 1).toLowerCase() + tempFieldName.substring(1);Class clazz = ClassUtils.getElementType(target, fieldName);retList.add(BeanUtils.convert(source, clazz));}return retList;} else if (value instanceof Map) {// TODO 暂时用不到,后续有需要再补充} else if (!ClassUtils.isPrimitive(targetClazz)) {return BeanUtils.convert(value, targetClazz);}return value;}}/** * @description 获取BeanCopier * @param source * @param target * @return * @return BeanCopier */public static BeanCopier getBeanCopier(Class<?> source, Class<?> target) {String beanCopierKey = generateBeanKey(source, target);if (beanCopierMap.containsKey(beanCopierKey)) {return beanCopierMap.get(beanCopierKey);} else {BeanCopier beanCopier = BeanCopier.create(source, target, true);beanCopierMap.putIfAbsent(beanCopierKey, beanCopier);}return beanCopierMap.get(beanCopierKey);}/** * @description 生成两个类的key * @param source * @param target * @return * @return String */public static String generateBeanKey(Class<?> source, Class<?> target) {return source.getName() + "@" + target.getName();}}

2.ClassUtils

package org.example.common.copier;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.util.HashMap;import java.util.Date;import java.util.Map;public class ClassUtils {private static final Map<Class<?>, Class<?>> primitiveMap = new HashMap<>(9);static {primitiveMap.put(String.class, String.class);primitiveMap.put(Boolean.class, boolean.class);primitiveMap.put(Byte.class, byte.class);primitiveMap.put(Character.class, char.class);primitiveMap.put(Double.class, double.class);primitiveMap.put(Float.class, float.class);primitiveMap.put(Integer.class, int.class);primitiveMap.put(Long.class, long.class);primitiveMap.put(Short.class, short.class);                primitiveMap.put(Date.class, Date.class);       }/**          * @description 判断基本类型          * @see     java.lang.String#TYPE          * @see     java.lang.Boolean#TYPE          * @see     java.lang.Character#TYPE          * @see     java.lang.Byte#TYPE          * @see     java.lang.Short#TYPE          * @see     java.lang.Integer#TYPE          * @see     java.lang.Long#TYPE          * @see     java.lang.Float#TYPE          * @see     java.lang.Double#TYPE          * @see     java.lang.Boolean#TYPE          * @see     char#TYPE          * @see     byte#TYPE          * @see     short#TYPE          * @see     int#TYPE          * @see     long#TYPE          * @see     float#TYPE          * @see     double#TYPE  * @param clazz  * @return boolean */public static boolean isPrimitive(Class<?> clazz) {if (primitiveMap.containsKey(clazz)) {return true;}return clazz.isPrimitive();}/** * @description 获取方法返回值类型 * @param tartget * @param fieldName * @return * @return Class<?> */public static Class<?> getElementType(Class<?> tartget, String fieldName) {Class<?> elementTypeClass = null;try {Type type = tartget.getDeclaredField(fieldName).getGenericType();ParameterizedType t = (ParameterizedType) type;String classStr = t.getActualTypeArguments()[0].toString().replace("class ", "");    elementTypeClass = Thread.currentThread().getContextClassLoader().loadClass(classStr);} catch (ClassNotFoundException | NoSuchFieldException | SecurityException e) {throw new RuntimeException("get fieldName[" + fieldName + "] error", e);}return elementTypeClass;}}


1 0
原创粉丝点击