copyProperties(...) 在 org.springframework.beans.BeanUtils 下,在正常应用中,开发者若是须要转换 bean,一般使用到的方法是:java
// originBean 是原型 // targetBean 是要转换的目标 BeanUtils.copyProperties(originBean, targetBean);
在 BeanUtils 中,copyProperties 有一系列的重载方法,可是最后都会落到一个具体的实现上:spring
/** * source - origin bean * target - 目标 bean * editable - 这个 class 对象用于设置对 target 的抽象层次 * ignoreProperties - 要忽略的参数 **/ private static void copyProperties(Object source, Object target, @Nullable Class<?> editable, @Nullable String... ignoreProperties) throws BeansException { // 判空,两个主要的 java 对象是不可为空的 Assert.notNull(source, "Source must not be null"); Assert.notNull(target, "Target must not be null"); /** * 获取 target 的 class 对象,若是设置了泛型,则默认使用泛型 * 若是 editable 是 null,则此处忽略 * 一般状况下是 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; } // 此处获取 target class 中的全部属性的描述 PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable); // 是否有须要忽略的属性 List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null); // 此处轮询全部的属性 for (PropertyDescriptor targetPd : targetPds) { // 获取写入方法,通常来讲即为 setXX(...) Method writeMethod = targetPd.getWriteMethod(); // 确认此属性并不被忽略,且存在写入方法 if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) { PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName()); if (sourcePd != null) { // 此处获取 source 中的对应属性的读取方法,通常来讲即为 getXX(...) Method readMethod = sourcePd.getReadMethod(); if (readMethod != null) { // 获取 readMethod 的返回值类型 ResolvableType sourceResolvableType = ResolvableType.forMethodReturnType(readMethod); // 获取 writeMethod 的第一个入参类型 ResolvableType targetResolvableType = ResolvableType.forMethodParameter(writeMethod, 0); // 此处判断 readMethod 的返回类型和 writeMethod 的入参类型是否为继承关系 // 只有当这二者为继承关系,或者相等的状况下,才会进行注入 boolean isAssignable = (sourceResolvableType.hasUnresolvableGenerics() || targetResolvableType.hasUnresolvableGenerics() ? ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType()) : targetResolvableType.isAssignableFrom(sourceResolvableType)); if (isAssignable) { 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 ex) { throw new FatalBeanException( "Could not copy property '" + targetPd.getName() + "' from source to target", ex); } } } } } } }