我在 Spring 的 BeanUtils 踩到的那些坑,千万不要犯!
Java后端技术
共 10424字,需浏览 21分钟
·
2021-03-20 09:30
往期热门文章:
1、《往期精选优秀博文都在这里了!》 2、分库分表?如何做到永不迁移数据和避免热点? 3、36 张图梳理 Intellij IDEA 常用设置,写代码贼爽! 4、2020年国内互联网公司的薪酬排名! 5、不要再封装各种Util工具类了,这个神级框架值得拥有!
private List<Order> orders;
private AddRequest.Ticket ticket;
private List<Payment> payments;
@ToString
@Data
public class CopyTest1 {
public String outerName;
public CopyTest1.InnerClass innerClass;
public List<CopyTest1.InnerClass> clazz;
@ToString
@Data
public static class InnerClass {
public String InnerName;
}
}
@ToString
@Data
public class CopyTest2 {
public String outerName;
public CopyTest2.InnerClass innerClass;
public List<CopyTest2.InnerClass> clazz;
@ToString
@Data
public static class InnerClass {
public String InnerName;
}
}
CopyTest1 test1 = new CopyTest1();
test1.outerName = "hahaha";
CopyTest1.InnerClass innerClass = new CopyTest1.InnerClass();
innerClass.InnerName = "hohoho";
test1.innerClass = innerClass;
System.out.println(test1.toString());
CopyTest2 test2 = new CopyTest2();
BeanUtils.copyProperties(test1, test2);
System.out.println(test2.toString());
CopyTest1 test1 = new CopyTest1();
test1.outerName = "hahaha";
CopyTest1.InnerClass innerClass = new CopyTest1.InnerClass();
innerClass.InnerName = "hohoho";
test1.innerClass = innerClass;
System.out.println(test1.toString());
CopyTest2 test2 = new CopyTest2();
test2.innerClass = new CopyTest2.InnerClass();
BeanUtils.copyProperties(test1, test2);
BeanUtils.copyProperties(test1.innerClass, test2.innerClass);
System.out.println(test2.toString());
总结
Spring的BeanUtils的CopyProperties方法需要对应的属性有getter和setter方法; 如果存在属性完全相同的内部类,但是不是同一个内部类,即分别属于各自的内部类,则spring会认为属性不同,不会copy; 泛型只在编译期起作用,不能依靠泛型来做运行期的限制; 最后,spring和apache的copy属性的方法源和目的参数的位置正好相反,所以导包和调用的时候都要注意一下。
最后的最后
private static void copyProperties(Object source, Object target, @Nullable Class<?> editable, @Nullable String... ignoreProperties) throws BeansException {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Class<?> actualEditable = target.getClass();
if (editable != null) {
if (!editable.isInstance(target)) {
throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]");
}
actualEditable = editable;
}
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
List<String> ignoreList = ignoreProperties != null ? Arrays.asList(ignoreProperties) : null;
PropertyDescriptor[] var7 = targetPds;
int var8 = targetPds.length;
for(int var9 = 0; var9 < var8; ++var9) {
PropertyDescriptor targetPd = var7[var9];
Method writeMethod = targetPd.getWriteMethod();
if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
if (sourcePd != null) {
Method readMethod = sourcePd.getReadMethod();
if (readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
try {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
Object value = readMethod.invoke(source);
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
writeMethod.invoke(target, value);
} catch (Throwable var15) {
throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", var15);
}
}
}
}
}
}
往期热门文章:
1、《历史文章分类导读列表!精选优秀博文都在这里了!》
2、阿里一面:如何保障消息100%投递成功、消息幂等性? 3、GitHub 热榜:被网友疯狂恶搞的「蚂蚁呀嘿」项目终于开源了! 4、记住!看小电影前一定要检查一下域名是不是 HTTPS 的,不然.... 5、拿到年终奖后马上辞职,厚道吗? 6、Redis 内存满了怎么办? 7、在 IDE 中玩转 GitHub 8、死磕18个Java8日期处理,工作必用! 9、把我坑惨的一个MySQL双引号! 10、2021年 我辞职了!
评论