Spring工具类BeanUtils.copyProperties源码解读

以前一直以为BeanUtils使用的反射,今天看了一下源码,才发现用的是内省,mark一下

关于内省的介绍:   https://blog.csdn.net/weixin_42069143/article/details/8211972

Demo代码:

             

@Test
public void beanUtilsCopy(){
    BeanWrapperPojo beanWrapperPojo = new BeanWrapperPojo();
    beanWrapperPojo.setAge(12);
    beanWrapperPojo.setName("Fev");
    BeanWrapperPojo beanWrapperPojo1 = new BeanWrapperPojo();
    BeanUtils.copyProperties(beanWrapperPojo,beanWrapperPojo1);
}

进入源码:

       

private static void copyProperties(Object source, Object target, @Nullable Class<?> editable, @Nullable String... ignoreProperties)

  此处有四个参数 :

          source:即源对象。

          target: 目标对象。

          editable:  用于验证目标对象是不是editable类型的。

          ignoreProperties: 需要忽视的对象。

 

具体源码:

        

 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、如果 参数editable不为空,则判断target是不是editable的实例。

                2、 之后获取目标类target的PropertyDescriptor[]

                PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);

                           方法getPropertyDescriptors(actualEditable);这里是获取PropertyDescriptor的操作并将其放入缓存中,为了防止并发,是通过actualEditable与其对应的PropertyDescriptor[]放在ConcurrentReferenceHashMap中。

               3、之后则是循环PropertyDescriptor[],如果PropertyDescriptor在ignoreProperties中则跳过,如果不在,则进行赋值:

                   首先通过目标对象的生效名称获取对应源对象的PropertyDescriptor :

                        PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());

                               之后通过目标对象PropertyDescriptor 的getWriteMethod()方法以及源对象PropertyDescriptor的getReadMethod进行值的读取与赋值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值