javabean属性复制BeanUtil

来源:互联网 发布:如何在淘宝上买发票啊 编辑:程序博客网 时间:2024/06/08 17:26
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);                    }                }            }        }    }}

原创粉丝点击