2019独角兽企业重金招聘Python工程师标准>>>
1. 用法
例如: BeanUtils.copyProperties(beforeObj, route, new String[] { "id", "createDate", "modifyDate" });
包名为:org.springframework.beans
2. 源代码分析
private static void copyProperties(Object source, Object target, Class editable, String... ignoreProperties)
throws BeansException {
/**
* 判断源对象和目标对象是否为空
*/
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
/**
* 当前目标对象类的Class对象
* java.lang.Class类里边有很多实用的方法 当你得到一个对象的Class对象之后就可以调用这些方法
* 例如:
* Method m = gTResultVo.getClass().getDeclaredMethod("set" + classMethod, String.class);
* m.invoke(gTResultVo, value);
* 通过Class类的getDeclaredMethod获取gTResultVo类的某个set方法,然后进行赋值
*/
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类表示JavaBean类通过存储器导出一个属性。
* 主要方法:
* 1、getPropertyType(),获得属性的Class对象。
* 2、getReadMethod(),获得用于读取属性值的方法;getWriteMethod(),获得用于写入属性值的方法。
* 3、hashCode(),获取对象的哈希值。
* 4、setReadMethod(Method readMethod),设置用于读取属性值的方法;setWriteMethod(MethodwriteMethod),设置用于写入属性值的方法;
*/
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
/**
* Arrays.asList(ignoreProperties):把String[]转换成列表
*/
List ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
for (PropertyDescriptor targetPd : targetPds) {
Method writeMethod = targetPd.getWriteMethod();//获得用于写入属性值的方法
/**
* 判断是否有忽略属性或当前属性是否在忽略属性中
* !ignoreList.contains(targetPd.getName()):利用列表的contains直接判断是否含有该属性
*/
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);//获取source的该属性值
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
writeMethod.invoke(target, value);//利用获取到的writeMethod给target赋值
}
catch (Throwable ex) {
throw new FatalBeanException(
"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
}
}
}
}
}
}
public static boolean isAssignable(Class lhsType, Class rhsType) {
Assert.notNull(lhsType, "Left-hand side type must not be null");
Assert.notNull(rhsType, "Right-hand side type must not be null");
/**
* instanceof:
* 用法:boolean 对象 instanceof 类型
* 解释:用于判断某一个对象是否是该类型的实例
*
* Class.isAssignableFrom(Class clazz)
* 用法:boolean class.isAssignableFrom(Class clazz)
* 解释:calss是否与参数clazz相同,或class是clazz的父类或接口。
*/
if (lhsType.isAssignableFrom(rhsType)) {
return true;
}
/**
* isPrimitive:确定指定的Class对象表示一个基本类型,当且仅当这个类表示一个基本类型此方法返回true。
* primitiveWrapperTypeMap:包装类作为key,原始类型作为value的基本类型集合;例如:primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
*/
if (lhsType.isPrimitive()) {
Class resolvedPrimitive = primitiveWrapperTypeMap.get(rhsType);
if (lhsType == resolvedPrimitive) {
return true;
}
}
/**
* primitiveTypeToWrapperMap:原始类型作为key,包装类作为value的基本类型集合;
*/
else {
Class resolvedWrapper = primitiveTypeToWrapperMap.get(rhsType);
if (resolvedWrapper != null && lhsType.isAssignableFrom(resolvedWrapper)) {
return true;
}
}
return false;
}