Bean拷贝

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;  
    }  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值