BeanUtils提供对Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度。
1、字段不统一的情况
如果User和UserActionForm 间存在名称不相同的属性,则BeanUtils不对这些属性进行处理,需要手动处理。例如:

User类里面有个createDate 创建时间字段,而User2里面无此字段。BeanUtils.copyProperties()不会对此字段做任何处理。必须要自己手动处理。
2、拷贝含有java.sql.Time,java.sql.Timestamp,java.io.File,java.net.URL等类型的null属性也会有类似的问题,使用时需要多加小心。
问题:
1.当源对象(a)中存在一个java.sql.Date类型的属性并且值为null,目标对象(b)中也存在这个同名同类型的属性。把a对象属性值copy给b时BeanUtils.copyProperties(b, a);会抛出异常;

2.当源对象(a)中存在一个java.sql.Date类型的属性并且值为null,目标对象(b)不存在这个同名同类型的属性,copy时没问题。
解决方法:

BeanUtilsBean.getInstance().getConvertUtils().register(new SqlDateConverter(null),Date.class);
//前面加上行代码即可
BeanUtils.copyProperties(b, a);
//第二种方法
把java.sql.Date改为java.util.Date也可以解决问题。
//第三种方法
把java.sql.Date的转化器去掉ConvertUtils.deregister(Date.class);

总结:在字段属性比较明确并且较少的情况下,单单为了简化代码或者使代码优雅而引入BeanUtils这种相对复杂的copy机制是否值得,需要权衡,毕竟它增加了复杂性也牺牲了一些性能的。
3、在使用复制的时候忽略null的属性

public class CopyUtils {
    //处理方法,可直接调用
    public static String[] getNullPropertyNames (Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        for(java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) emptyNames.add(pd.getName());
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    public static void copyProperties(Object src, Object target) {
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
    }
}

4、性能问题
经过测试发现,在使用这个方法的时候比使用set,get设置有明显的性能下降的现象。
我们可以使用一个方法解决:ReflectASM,高性能的反射。
什么是ReflectASM ReflectASM是一个很小的java类库,主要是通过asm生产类来实现java反射,执行速度非常快,看了网上很多和反射的对比,觉得ReflectASM比较神奇,很想知道其原理,下面介绍下如何使用及原理;

public static void main(String[] args) {    
        User user = new User();    
        //使用reflectasm生产User访问类    
        MethodAccess access = MethodAccess.get(User.class);    
        //invoke setName方法name值    
        access.invoke(user, "setName", "张三");    
        //invoke getName方法 获得值    
        String name = (String)access.invoke(user, "getName", null);    
        System.out.println(name);    
    }    
    private static Map<Class, MethodAccess> methodMap = new HashMap<Class, MethodAccess>();
 
	private static Map<String, Integer> methodIndexMap = new HashMap<String, Integer>();
 
	private static Map<Class, List<String>> fieldMap = new HashMap<Class, List<String>>();
 
	public static void copyProperties(Object desc, Object orgi) {
		MethodAccess descMethodAccess = methodMap.get(desc.getClass());
		if (descMethodAccess == null) {
			descMethodAccess = cache(desc);
		}
		MethodAccess orgiMethodAccess = methodMap.get(orgi.getClass());
		if (orgiMethodAccess == null) {
			orgiMethodAccess = cache(orgi);
		}
 
		List<String> fieldList = fieldMap.get(orgi.getClass());
		for (String field : fieldList) {
			String getKey = orgi.getClass().getName() + "." + "get" + field;
			String setkey = desc.getClass().getName() + "." + "set" + field;
			Integer setIndex = methodIndexMap.get(setkey);
			if (setIndex != null) {
				int getIndex = methodIndexMap.get(getKey);
				// 参数一需要反射的对象
				// 参数二class.getDeclaredMethods 对应方法的index
				// 参数对三象集合
				descMethodAccess.invoke(desc, setIndex.intValue(),
						orgiMethodAccess.invoke(orgi, getIndex));
			}
		}
	}
 
	// 单例模式
	private static MethodAccess cache(Object orgi) {
		synchronized (orgi.getClass()) {
			MethodAccess methodAccess = MethodAccess.get(orgi.getClass());
			Field[] fields = orgi.getClass().getDeclaredFields();
			List<String> fieldList = new ArrayList<String>(fields.length);
			for (Field field : fields) {
				if (Modifier.isPrivate(field.getModifiers())
						&& !Modifier.isStatic(field.getModifiers())) { // 是否是私有的,是否是静态的
					// 非公共私有变量
					String fieldName = StringUtils.capitalize(field.getName()); // 获取属性名称
					int getIndex = methodAccess.getIndex("get" + fieldName); // 获取get方法的下标
					int setIndex = methodAccess.getIndex("set" + fieldName); // 获取set方法的下标
					methodIndexMap.put(orgi.getClass().getName() + "." + "get"
							+ fieldName, getIndex); // 将类名get方法名,方法下标注册到map中
					methodIndexMap.put(orgi.getClass().getName() + "." + "set"
							+ fieldName, setIndex); // 将类名set方法名,方法下标注册到map中
					fieldList.add(fieldName); // 将属性名称放入集合里
				}
			}
			fieldMap.put(orgi.getClass(), fieldList); // 将类名,属性名称注册到map中
			methodMap.put(orgi.getClass(), methodAccess);
			return methodAccess;
		}
	}

以上就是在使用beanUtils属性赋值的时候的一点总结。希望对大家有用!