BeanUtils 的 copyProperties 踩坑记录
代码示例
import org.apache.commons.beanutils.BeanUtils;
public class TestBeanUtils {
public static void main(String[] args) throws Exception {
testApacheBeanUtils();
testSpringBeanUtils();
}
private static void testSpringBeanUtils() {
User user = new User().setUsername("lisi").setPwd("123");
User copyUser = new User();
// 目标对象在后
org.springframework.beans.BeanUtils.copyProperties(user, copyUser);
System.out.println(copyUser);// User{username='lisi', pwd='123'}
}
private static void testApacheBeanUtils() throws Exception {
User user = new User().setUsername("lisi").setPwd("123");
User copyUser = new User();
// 目标对象在前
BeanUtils.copyProperties(copyUser, user);
System.out.println(copyUser); // User{username='null', pwd='null'}
}
public static class User {
private String username;
private String pwd;
public User setUsername(String username) {
this.username = username;
return this;
}
public String getUsername() {
return username;
}
public User setPwd(String pwd) {
this.pwd = pwd;
return this;
}
public String getPwd() {
return pwd;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
}
测试使用 apache 及 spring 的 copyProperties 功能,在上述场景中,apache 的 BeanUtils 不能 copy 属性值。
原因分析
apache 的 BeanUtils 的 copyProperties 最终使用的是 java 内部的 Introspector 的 getTargetPropertyInfo() 来获取可 copy 所有属性,默认取返回类型为 void 的 set 方法
spring 的 BeanUtils 通过 ExtendedBeanInfo(继承 BeanInfo) 重写了获取 set 方法的逻辑,所以不存在这个问题。
总结
使用 BeanUtils 的 copyProperties 功能,虽然可以少写很多代码,但很容易踩坑,还有一个问题就是,后续如果我们想根据属性名定位到哪些地方使用了(set),也没办法定位。