import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.Map; import lombok.extern.slf4j.Slf4j; /** * 实体复制工具类 * * @Date 2015年2月12日 */ @Slf4j public class BeanCopyUtil { /** * 对象数据复制(浅复制),目标对象中属性如果与源对象中属性类型不致,则不进行复制,需要额外处理 * * @date 2015-02-12 * @param toClazz 目标对象类型 * @param fromObj 源数据对象 * @return 根据源数据对象复制数据后新生成的对象 * @throws Exception toClazz或fromObj为空时抛错 */ @SuppressWarnings("unchecked") public static <T> T copyBeanProperties(Object srcObj, Class<T> toClazz) throws Exception { if (toClazz == null || srcObj == null) { throw new Exception("目标对象类型或源数据对象不能为空!"); } //创建返回对象实例 Object destObj = toClazz.getConstructor().newInstance(); execCopy(srcObj, destObj); // 返回对象 return (T) destObj; } /** * 对象数据复制(浅复制),目标对象中属性如果与源对象中属性类型不致,则不进行复制,需要额外处理 * * @date 2015-02-12 * @param toClazz 目标对象类型 * @param fromObj 源数据对象 * @return 根据源数据对象复制数据后新生成的对象 * @throws Exception toClazz或fromObj为空时抛错 */ public static void copyBeanProperties(Object srcObj, Object destObj) throws Exception { if (destObj == null || srcObj == null) { throw new Exception("目标对象类型或源数据对象不能为空!"); } execCopy(srcObj, destObj); } /** * 对象数据复制(浅复制),目标对象中属性如果与源对象中属性类型不致,则不进行复制,需要额外处理 * * @date 2015-02-12 * @param toClazz 目标对象类型 * @param fromObj 源数据对象 * @return 根据源数据对象复制数据后新生成的对象 * @throws Exception toClazz或fromObj为空时抛错 */ public static void execCopy(Object srcObj, Object destObj) throws Exception { // 目标Bean定义的属性列表 Field[] fields = destObj.getClass().getDeclaredFields(); // 目标Bean父类的属性列表 Field[] parentFields = destObj.getClass().getSuperclass().getDeclaredFields(); int fieldCount = 0; if (fields != null) { fieldCount = fields.length; } if (parentFields != null) { fieldCount += parentFields.length; } //根据当前目标对象定义的属性列表和其父类的属性列表创建用于数据COPY的属性列表 Field[] destFields = new Field[fieldCount]; System.arraycopy(fields, 0, destFields, 0, fields.length); System.arraycopy(parentFields, 0, destFields, fields.length, parentFields.length); //源对象的GET方法描述对象 PropertyDescriptor pdGetterWithFromObj = null; //目标对象的SET方法描述对象 PropertyDescriptor pdWithDestObj = null; // 拷贝属性值 for (Field f : destFields) { if ("serialVersionUID".equals(f.getName())) { continue; } //获取GETTER try { pdGetterWithFromObj = new PropertyDescriptor(f.getName(), srcObj.getClass()); } catch (IntrospectionException e) { // 原始对象中不包括该属性,继续拷贝 log.debug(String.format("警告: 源对象中不存在属性{%s}的GETTER方法!", f.getName()), e); continue; } // 获得SETTER try { pdWithDestObj = new PropertyDescriptor(f.getName(), destObj.getClass()); } catch (IntrospectionException e) { // 原始对象中不包括该属性,继续拷贝 log.debug(String.format("警告: 源对象中不存在属性{%s}的SETTER方法!", f.getName()), e); continue; } /*** 数据复制操作 */ //获取数据值 Object value = pdGetterWithFromObj.getReadMethod().invoke(srcObj); //如果源对象中属性类型与目标对象中的属性类型不同,先进行类型转换,如果转换失败则跳过 if (value != null && !value.getClass().getName().equals(pdWithDestObj.getReadMethod().getReturnType().getName())) { try { value = covert(value, pdWithDestObj.getReadMethod().getReturnType()); } catch (Exception e) { log.debug("复制出错", e); continue; } } //执行COPY操作 try { pdWithDestObj.getWriteMethod().invoke(destObj, value); } catch (Exception e) { log.debug(String.format("警告: 目标对象中属性{%s},与源对象中属性{%s}数据类型不一致,复制操作被过滤!", f.getName(), f.getName()), e); continue; } } } @SuppressWarnings("rawtypes") private static Object covert(Object value, Class type) throws Exception { Object dest = null; if (type.equals(String.class)) { dest = String.valueOf(value); } else if (type.equals(Integer.class)) { dest = Integer.valueOf(String.valueOf(value)); } else if (type.equals(Byte.class)) { dest = Byte.valueOf(String.valueOf(value)); } else if (type.equals(Double.class)) { dest = Double.valueOf(String.valueOf(value)); } return dest; } /** * Converts a map to a JavaBean. * * @param type type to convert * @param map map to convert * @return JavaBean converted * @throws IntrospectionException failed to get class fields * @throws IllegalAccessException failed to instant JavaBean * @throws InstantiationException failed to instant JavaBean * @throws InvocationTargetException failed to call setters */ public static final Object toBean(Class<?> type, Map<String, ? extends Object> map) throws IntrospectionException, IllegalAccessException, InstantiationException, InvocationTargetException { BeanInfo beanInfo = Introspector.getBeanInfo(type); Object obj = type.newInstance(); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (int i = 0; i< propertyDescriptors.length; i++) { PropertyDescriptor descriptor = propertyDescriptors[i]; String propertyName = descriptor.getName(); if (map.containsKey(propertyName)) { Object value = map.get(propertyName); Object[] args = new Object[1]; args[0] = value; descriptor.getWriteMethod().invoke(obj, args); } } return obj; } }
Bean拷贝
最新推荐文章于 2024-07-24 17:33:46 发布