import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.FatalBeanException; /** * bean的属性拷贝工具类 */ public class BeanUtil { private static final Log logger = LogFactory.getLog(BeanUtil.class); /** bean嵌套 */ private static final String NESTED = "."; /** * 复制bean的属性(支持嵌套属性,以点号分割) * * @param source * 拷贝属性的源对象 * * @param dest * 拷贝属性的目的地对象 * * @param includeProperties * 拷贝的属性列表 * * @author yang_qiao * * @throws InvocationTargetException * * @throws IllegalAccessException * * @throws IllegalArgumentException * * @throws InstantiationException * * @throws IntrospectionException * * @date 2013-12-18 */ public static final void copyIncludeProperties(final Object source, Object dest, final String[] includeProperties) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, IntrospectionException { if (includeProperties == null || includeProperties.length == 0) { throw new IllegalArgumentException("未传入要拷贝的属性列表"); } if (source == null) { throw new IllegalArgumentException("要拷贝的源对象为空"); } if (dest == null) { throw new IllegalArgumentException("要拷贝的目的对象为空"); } // 日志信息 if (logger.isTraceEnabled()) { logger.trace("[source bean: " + source.getClass().getName() + " ]"); logger.trace("[destination bean: " + dest.getClass().getName() + " ]"); } // 拷贝 for (String property : includeProperties) { PropertyDescriptor sourcePropertyDescriptor = null; PropertyDescriptor destPropertyDescriptor = null; if (isSimpleProperty(property)) { // 简单属性 sourcePropertyDescriptor = getProperty(property, source); destPropertyDescriptor = getProperty(property, dest); if (sourcePropertyDescriptor == null) { throw new IllegalArgumentException("要拷贝的源对象不存在该属性"); } if (destPropertyDescriptor == null) { throw new IllegalArgumentException("要拷贝到的目标对象不存在该属性"); } copyProperty(property, source, dest); } else { // 嵌套bean属性 Object target = dest; Object realSource = source; String[] nestedProperty = getNestedProperty(property); if (nestedProperty != null && nestedProperty.length > 1) { for (int i = 0; i < nestedProperty.length - 1; i++) { sourcePropertyDescriptor = getProperty( nestedProperty[i], realSource); destPropertyDescriptor = getProperty(nestedProperty[i], target); if (sourcePropertyDescriptor == null) { throw new IllegalArgumentException("要拷贝的源对象不存在该属性"); } if (destPropertyDescriptor == null) { throw new IllegalArgumentException( "要拷贝到的目标对象不存在该属性"); } Method readMethod = sourcePropertyDescriptor .getReadMethod(); realSource = readMethod.invoke(realSource); readMethod = destPropertyDescriptor.getReadMethod(); Method writeMethod = destPropertyDescriptor .getWriteMethod(); Object value = readMethod.invoke(target); if (value == null) { value = destPropertyDescriptor.getPropertyType() .newInstance(); writeMethod.invoke(target, value); } target = value; } final String prop = nestedProperty[nestedProperty.length - 1]; sourcePropertyDescriptor = getProperty(prop, realSource); destPropertyDescriptor = getProperty(prop, target); if (sourcePropertyDescriptor == null) { throw new IllegalArgumentException("要拷贝的源对象不存在该属性"); } if (destPropertyDescriptor == null) { throw new IllegalArgumentException("要拷贝到的目标对象不存在该属性"); } copyProperty(prop, realSource, target); } } } } /** * 复制bean的属性(支持嵌套属性,以点号分割) * * @param source * 拷贝属性的源对象 * * @param dest * 拷贝属性的目的地对象 * * @param includeProperties * 拷贝的属性列表 * * @throws IntrospectionException * * @throws InvocationTargetException * * @throws IllegalAccessException * * @throws IllegalArgumentException * * @throws InstantiationException * * @throws ClassNotFoundException * * @throws IOException * */ public static void copyProperties(final Object source, final Object dest, final String... excludeProperties) throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException, ClassNotFoundException { final Object backupSource = clone(dest); if (source == null) { throw new IllegalArgumentException("要拷贝的源对象为空"); } if (dest == null) { throw new IllegalArgumentException("要拷贝的目的对象为空"); } org.apache.commons.beanutils.BeanUtils.copyProperties(dest, source); // 还原排除的属性值 revertProperties(backupSource, dest, excludeProperties); } /** * 从备份对象中还原属性 * * @param backup * 备份bean * * @param target * 目标bean * * @param properties * 属性列表 * * @throws InvocationTargetException * * @throws IllegalAccessException * * @throws IllegalArgumentException * * @throws IntrospectionException * * @throws InstantiationException */ private static void revertProperties(final Object backup, Object target, final String... properties) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IntrospectionException, InstantiationException { if (properties == null || properties.length == 0) { return; } if (backup == null) { throw new IllegalArgumentException("备份对象为空"); } if (target == null) { throw new IllegalArgumentException("目的对象为空"); } // 日志信息 if (logger.isTraceEnabled()) { logger.trace("[source bean: " + backup.getClass().getName() + " ]"); logger.trace("[destination bean: " + target.getClass().getName() + " ]"); } // 拷贝 for (String property : properties) { PropertyDescriptor sourcePropertyDescriptor = null; PropertyDescriptor destPropertyDescriptor = null; if (isSimpleProperty(property)) { // 简单属性 sourcePropertyDescriptor = getProperty(property, backup); destPropertyDescriptor = getProperty(property, target); if (sourcePropertyDescriptor == null) { throw new IllegalArgumentException("要拷贝的源对象不存在该属性"); } if (destPropertyDescriptor == null) { throw new IllegalArgumentException("要拷贝到的目标对象不存在该属性"); } copyProperty(property, backup, target); } else { // 嵌套bean属性 Object targetObj = target; Object realBackup = backup; String[] nestedProperty = getNestedProperty(property); if (nestedProperty != null && nestedProperty.length > 1) { for (int i = 0; i < nestedProperty.length - 1; i++) { sourcePropertyDescriptor = getProperty( nestedProperty[i], realBackup); destPropertyDescriptor = getProperty(nestedProperty[i], targetObj); if (sourcePropertyDescriptor == null) { throw new IllegalArgumentException("要拷贝的源对象不存在该属性"); } if (destPropertyDescriptor == null) { throw new IllegalArgumentException( "要拷贝到的目标对象不存在该属性"); } Method readMethod = sourcePropertyDescriptor .getReadMethod(); realBackup = readMethod.invoke(realBackup); if (realBackup == null) { // 判断备份对象嵌套属性是否为空 realBackup = sourcePropertyDescriptor .getPropertyType().newInstance(); } Method writeMethod = destPropertyDescriptor .getWriteMethod(); readMethod = destPropertyDescriptor.getReadMethod(); Object value = readMethod.invoke(targetObj); if (value == null) { value = destPropertyDescriptor.getPropertyType() .newInstance(); writeMethod.invoke(targetObj, value); } targetObj = value; } final String prop = nestedProperty[nestedProperty.length - 1]; sourcePropertyDescriptor = getProperty(prop, realBackup); destPropertyDescriptor = getProperty(prop, targetObj); if (sourcePropertyDescriptor == null) { throw new IllegalArgumentException("要拷贝的源对象不存在该属性"); } if (destPropertyDescriptor == null) { throw new IllegalArgumentException("要拷贝到的目标对象不存在该属性"); } copyProperty(prop, realBackup, targetObj); } } } } /** * 对象克隆 */ private static Object clone(final Object value) throws IOException, ClassNotFoundException { // 字节数组输出流,暂存到内存中 ByteArrayOutputStream bos = new ByteArrayOutputStream(); // 序列化 ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(value); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); // 反序列化 return ois.readObject(); } /** * 判断是否为简单属性,是,返回ture * * @author yang_qiao * * @date 2013-12-18 */ private static boolean isSimpleProperty(final String property) { return !property.contains(NESTED); } /** * 获取目标bean的属性 */ private static PropertyDescriptor getProperty(final String propertyName, final Object target) { if (target == null) { new IllegalArgumentException("查询属性的对象为空"); } if (propertyName == null || "".equals(propertyName)) { new IllegalArgumentException("查询属性不能为空值"); } PropertyDescriptor propertyDescriptor = null; try { propertyDescriptor = new PropertyDescriptor(propertyName, target.getClass()); } catch (IntrospectionException e) { logger.info("不存在该属性"); return null; } return propertyDescriptor; } /** * 单个属性复制--原数据源和目的数据源必须要有该属性方可 * * @throws InvocationTargetException * * @throws IllegalAccessException * * @throws IllegalArgumentException * * @throws IntrospectionException */ public static void copyProperty(final String propertyName, final Object source, Object dest) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IntrospectionException { PropertyDescriptor property; property = new PropertyDescriptor(propertyName, source.getClass()); Method getMethod = property.getReadMethod(); Object value = getMethod.invoke(source); property = new PropertyDescriptor(propertyName, dest.getClass()); Method setMethod = property.getWriteMethod(); setMethod.invoke(dest, value); } /** * 获取嵌套Bean的属性 * * @author yang_qiao * * @date 2013-12-18 */ public static String[] getNestedProperty(final String nestedProperty) { if (nestedProperty == null || "".equals(nestedProperty)) { new IllegalArgumentException("参数为空值"); } return nestedProperty.split("\\" + NESTED); } /** * 忽略null拷贝属性值 * @param source * @param target * @throws BeansException */ public static void copyProperties(Object source, Object target) throws BeansException { if (source == null) { throw new IllegalArgumentException("要拷贝的源对象为空"); } if (target == null) { throw new IllegalArgumentException("要拷贝的目的对象为空"); } Class<?> actualEditable = target.getClass(); PropertyDescriptor[] targetPds = org.springframework.beans.BeanUtils.getPropertyDescriptors(actualEditable); for (PropertyDescriptor targetPd : targetPds) { if (targetPd.getWriteMethod() != null) { PropertyDescriptor sourcePd = org.springframework.beans.BeanUtils.getPropertyDescriptor(source.getClass(), targetPd.getName()); if (sourcePd != null && sourcePd.getReadMethod() != null) { try { Method readMethod = sourcePd.getReadMethod(); if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { readMethod.setAccessible(true); } Object value = readMethod.invoke(source); // 这里判断以下value是否为空 当然这里也能进行一些特殊要求的处理 例如绑定时格式转换等等 if (value != null) { Method writeMethod = targetPd.getWriteMethod(); if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { writeMethod.setAccessible(true); } writeMethod.invoke(target, value); } } catch (Throwable ex) { throw new FatalBeanException("Could not copy properties from source to target", ex); } } } } } }
javabean属性复制BeanUtil
猜你喜欢
转载自blog.csdn.net/duoluo9/article/details/78530015
今日推荐
周排行