package com.fpi.spring.qaepb.cps.util; 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 org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.fpi.spring.qaepb.cps.entity.po.Project; import com.fpi.spring.qaepb.cps.entity.po.ProjectApproval; /** * bean的属性拷贝工具类 * * @date 2013-12-17 * * @author yang_qiao * * @version 1.0 */ public class BeanUtils { private static final Log logger = LogFactory.getLog(BeanUtils.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 * 拷贝的属性列表 * * @author yang_qiao * * @throws IntrospectionException * * @throws InvocationTargetException * * @throws IllegalAccessException * * @throws IllegalArgumentException * * @throws InstantiationException * * @throws ClassNotFoundException * * @throws IOException * * @date 2013-12-18 */ 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 * 属性列表 * * @author yang_qiao * * @throws InvocationTargetException * * @throws IllegalAccessException * * @throws IllegalArgumentException * * @throws IntrospectionException * * @throws InstantiationException * * @date 2013-12-18 */ 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); } } } } /** * 对象克隆 * * @author yang_qiao * * @date 2013-12-18 */ 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的属性 * * @author yang_qiao * * @date 2013-12-17 */ 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; } /** * 单个属性复制--原数据源和目的数据源必须要有该属性方可 * * @author yang_qiao * * @throws InvocationTargetException * * @throws IllegalAccessException * * @throws IllegalArgumentException * * @throws IntrospectionException * * @date 2013-12-17 */ 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); } public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, IntrospectionException, IOException, ClassNotFoundException { Project oldProject = new Project(); Project newProject = new Project(); ProjectApproval projectApproval = new ProjectApproval(); projectApproval.setFirstCheckComment("jsoncheck"); projectApproval.setExplorationComment("shitCheck"); oldProject.setProjectApproval(projectApproval); oldProject.setBuildAddress("json"); oldProject.setContact("json"); final String[] includeProperties = new String[] { "contact", "projectApproval.firstCheckComment", "projectApproval.explorationComment" }; BeanUtils.copyIncludeProperties(oldProject, newProject, includeProperties); System.out.println(newProject.getContact()); System.out.println(newProject.getProjectApproval() .getFirstCheckComment()); System.out.println(newProject.getProjectApproval() .getExplorationComment()); System.out.println(newProject.getApprovalStatus()); System.out.println(newProject.getBuildAddress()); System.out.println("================================"); oldProject = new Project(); newProject = new Project(); projectApproval = new ProjectApproval(); projectApproval.setFirstCheckComment("jsoncheck_"); projectApproval.setExplorationComment("shitCheck_"); oldProject.setProjectApproval(projectApproval); oldProject.setBuildAddress("json_"); oldProject.setContact("json_"); final String[] excludeProperties = null; BeanUtils.copyProperties(oldProject, newProject, excludeProperties); System.out.println(newProject.getContact()); System.out.println(newProject.getProjectApproval() .getExplorationComment()); System.out.println(newProject.getProjectApproval() .getFirstCheckComment()); System.out.println(newProject.getApprovalStatus()); System.out.println(newProject.getBuildAddress()); } }