1.spring 中BeanUtils.copyProperties()
2.apache commons-beanutils 中BeanUtils.copyProperties()
3.apache commons-beanutils PropertyUtils.copyProperties(),三者比较
org.springframework.beans.BeanUtils与org.apache.commons.beanutils.BeanUtils都提供了copyProperties方法,作用是将一个Bean对象中的数据封装到另一个属性结构相似的Bean对象中
差异比较
1)两者的copyProperties方法参数位置不同
org.springframework.beans.BeanUtils: copyProperties(source, target)
org.apache.commons.beanutils.BeanUtils: copyProperties(target, source)
2)要求两个Bean的属性名相同,且有对应的setXxx方法和getXxx方法。其实底层原理是使用source的getXxx方法和target的setXxx方法
3)source有的属性而target没有的属性,不会封装到target对象中;
target有的属性而source没有的属性,会封装到target中,数据为默认值(注意基本类型默认值与引用类型默认值不同)
4)类型转换问题
a)基本类型与其对应的封装类型可以相互转换
b)org.springframework.beans.BeanUtils
与org.apache.commons.beanutils.BeanUtils对于String和Date类型转换的情况是不同的
日期转换注意事项
a. org.springframework.beans.BeanUtils.copyProperties
不可以将java.util.Date类型转换成String类型
b. org.apache.commons.beanutils.BeanUtils.copyProperties
可以将java.util.Date/java.sql.Date类型转换成String类型,但是转换后二者格式是不同的
测试效果:
java.util.Date–>String
[id=10,name=姓名,email=,createTime=Thu Jan 01 08:00:00 CST 1970]
java.sql.Date–>String
[id=10,name=姓名,email=,createTime=1970-01-01]
c . 无论是org.springframework.beans.BeanUtils
还是org.apache.commons.beanutils.BeanUtils,默认情况下都不能将String类型转成Date类型
高性能反射:reflectasm.jar
实现属性copy案例
package com.git.util;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import com.esotericsoftware.reflectasm.MethodAccess;
@SuppressWarnings(“rawtypes”)
public class Util {
private static String SET="set";
private static String GET="get";
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));
}
}
}
public 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());
//获取get/set方法下标
int getIndex = methodAccess.getIndex(GET+fieldName);
int setIndex = methodAccess.getIndex(SET+fieldName);
//将类名get/set方法名,下标注册到map中
methodIndexMap.put(orgi.getClass().getName()+"."+GET+fieldName, getIndex);
methodIndexMap.put(orgi.getClass().getName()+"."+SET+fieldName, setIndex);
// 将属性名称放入集合里
fieldList.add(fieldName);
}
}
//将类名,属性名称注册到map中
fieldMap.put(orgi.getClass(), fieldList);
methodMap.put(orgi.getClass(), methodAccess);
return methodAccess;
}
}
}