BeanUtils的包名:org.springframework.beans
BeanUtils.copyProperties(a,b); // 将a中的属性拷贝到b中
原理是通过java的反射机制,依赖set进行属性注入。
详细可以看源码。不过我比较懒,先进行了黑盒测试,然后大致的看了下源码。
源码是通过set进行注入的,以目标b属性为主从源数据a中获取值,
如果a中不存在该属性,则b中的属性不做任何操作,即值为null。
下面是部分源码,大概在301行的样子(毕竟版本不一样,行数可能有些差别)
Class<?> actualEditable = target.getClass();
// 省略部分代码
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);
}
}
}
}
}