org.springframework.beans.BeanUtils是Spring提供对Java反射和自省API的包装,其主要目的是利用反射机制对JavaBean的属性进行处理。实际使用当中我们可能只需要简单的复制值操作,那么就可以自己通过反射来实现此功能,而且可以根据自身的业务情况自定义功能。
下面是BeanUtils复制方法与自己编写根据反射复制方法在运行时间上做了对比,单单从相同字段复制来比较,自己写的方法少了很多验证和扩展机制,因此少了很多方法栈的调用,节省了大量时间。
分别使用不同的数据结构来减少对比次数,在属性值比较少的情况下,直接就可以使用两个数组嵌套迭代,其他扩展功能也可以自定义添加。
/**
* 利用两个数组迭代复制
*
* @param source
* @param target
*/
public static void copyFiled(Object source, Object target) {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Field[] sourceFields = source.getClass().getDeclaredFields();
Field[] targetFields = target.getClass().getDeclaredFields();
Object value;
int count = 0;
try {
for (Field field : sourceFields) {
for (Field field2: targetFields) {
count++;
if (field.getName().equals(field2.getName()) && field.getType().equals(field2.getType())) {
field.setAccessible(true);
value = field.get(source);
if (null == value || "" == value) {
continue;
}
field2.setAccessible(true);
field2.set(target, value);
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("迭代次数: " + count);
}
/**
* 利用一个数组和一个链表迭代复制
*
* @param source
* @param target
*/
public static void copyFiled2(Object source, Object target) {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Field[] sourceFields = source.getClass().getDeclaredFields();
Field[] targetFields = target.getClass().getDeclaredFields();
LinkedList<Field> link = new LinkedList<>(Arrays.asList(targetFields));
Object value;
int count = 0;
Field field2;
int len;
try {
for (Field field : sourceFields) {
len = link.size();
for (int i = 0; i < len; i++) {
count++;
field2 = link.get(i);
if (field.getName().equals(field2.getName()) && field.getType().equals(field2.getType())) {
field.setAccessible(true);
value = field.get(source);
if (null == value || "" == value) {
continue;
}
field2.setAccessible(true);
field2.set(target, value);
link.remove(i);
break;
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("迭代次数: " + count);
}
/**
* 利用一个数组和一个HashMap迭代复制
*
* @param source
* @param target
*/
public static void copyFiled3(Object source, Object target) {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Field[] sourceFields = source.getClass().getDeclaredFields();
Field[] targetFields = target.getClass().getDeclaredFields();
HashMap<String, Field> fieldMap = new HashMap<>(targetFields.length);
for (Field targetField : targetFields) {
fieldMap.put(targetField.getName(), targetField);
}
Object value;
int count = 0;
Field field2;
try {
for (Field field : sourceFields) {
count++;
field2 = fieldMap.get(field.getName());
if (field.getType().equals(field2.getType())) {
field.setAccessible(true);
value = field.get(source)
if (null == value || "" == value) {
continue;
}
field2.setAccessible(true);
field2.set(target, value);
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("迭代次数: " + count);
}
两个不同对象
@Data
public class User1 {
private Date date;
private Integer userId;
private String userName;
private Module module;
}
@Data
public class User2 {
private Integer userId;
private String userName;
private Date date;
private Module module;
}
分别利用不用方法执行对象复制
public static void main(String[] args) {
Module m = new Module();
m.setName("name");
User1 u1 = new User1();
u1.setUserId(1);
u1.setUserName("xiaoming");
u1.setDate(new Date());
u1.setModule(m);
long start, end;
User2 u3 = new User2();
start = System.currentTimeMillis();
copyFiled(u1, u3);
end = System.currentTimeMillis();
System.out.println("用时" + (end - start) + "毫秒");
User2 u4 = new User2();
start = System.currentTimeMillis();
copyFiled2(u1, u4);
end = System.currentTimeMillis();
System.out.println("用时" + (end - start) + "毫秒");
User2 u5 = new User2();
start = System.currentTimeMillis();
copyFiled3(u1, u5);
end = System.currentTimeMillis();
System.out.println("用时" + (end - start) + "毫秒");
User2 u2 = new User2();
start = System.currentTimeMillis();
org.springframework.beans.BeanUtils.copyProperties(u1, u2);
end = System.currentTimeMillis();
System.out.println("BeanUtils.copyProperties用时" + (end - start) + "毫秒");
}
执行结果