BeanUtils对象与对象关系映射的源码学习和优化

BeanUtils对象与对象关系映射的源码学习和优化

所需代码:commons-beanutils-1.7.0-sources.jar

背景:

数据入参vo对象映射到数据库bo对象的属性值的映射,出现了问题,所使用的jar包为apache commons-beanutils的commons-beanutils-1.7.0.jar(不是Spring)使用的方法为BeanUtils.copyProperties(dest, src );

问题:

当入参vo的String shopId的值为null的时候,使用BeanUtils.copyProperties(dest, src );后,bo中的String shopId值变成了"",然而入库的update的sql的限制条件为,导致insert的sql中原有数据被覆盖。

方案:
方案一:

修改apache commons-beanutils的源码

方案二:

修改mapper.xml中的代码限制条件改为

目标:

修改现有生成代码,从根源上限制vo属性为null的时候,导致bo为""的问题。

解决方案:

这里采用方案一的方式:

下载apache commons-beanutils的源码,使用ide中的source下载。

在这里插入图片描述

说明:

commons-beanutils-1.7.0.jar为maven项目中编译执行的class文件

commons-beanutils-1.7.0-sources.jar为maven项目中可查看的java文件

原有代码:

BeanUtils

    public static void copyProperties(Object dest, Object orig)
        throws IllegalAccessException, InvocationTargetException {
        
        BeanUtilsBean.getInstance().copyProperties(dest, orig);
    }

BeanUtilsBean

public void copyProperties(Object dest, Object orig)
    throws IllegalAccessException, InvocationTargetException {

    // Validate existence of the specified beans
    if (dest == null) {
        throw new IllegalArgumentException
                ("No destination bean specified");
    }
    if (orig == null) {
        throw new IllegalArgumentException("No origin bean specified");
    }
    if (log.isDebugEnabled()) {
        log.debug("BeanUtils.copyProperties(" + dest + ", " +
                  orig + ")");
    }

    // Copy the properties, converting as necessary
    if (orig instanceof DynaBean) {
        DynaProperty origDescriptors[] =
            ((DynaBean) orig).getDynaClass().getDynaProperties();
        for (int i = 0; i < origDescriptors.length; i++) {
            String name = origDescriptors[i].getName();
            if (getPropertyUtils().isWriteable(dest, name)) {
                Object value = ((DynaBean) orig).get(name);
                copyProperty(dest, name, value);
            }
        }
    } else if (orig instanceof Map) {
        Iterator names = ((Map) orig).keySet().iterator();
        while (names.hasNext()) {
            String name = (String) names.next();
            if (getPropertyUtils().isWriteable(dest, name)) {
                Object value = ((Map) orig).get(name);
                copyProperty(dest, name, value);
            }
        }
    } else /* if (orig is a standard JavaBean) */ {
        PropertyDescriptor origDescriptors[] =
            getPropertyUtils().getPropertyDescriptors(orig);
        for (int i = 0; i < origDescriptors.length; i++) {
            String name = origDescriptors[i].getName();
            if ("class".equals(name)) {
                continue; // No point in trying to set an object's class
            }
            if (getPropertyUtils().isReadable(orig, name) &&
                getPropertyUtils().isWriteable(dest, name)) {
                try {
                    Object value =
                        getPropertyUtils().getSimpleProperty(orig, name);
                    copyProperty(dest, name, value);
                } catch (NoSuchMethodException e) {
                    ; // Should not happen
                }
            }
        }
    }

}

上面代码为原有代码,如何理解,通过反射的方式,获取属性名,然后通过属性名相同的equals()判断是否相同,然后再复制copyProperty(dest, name, value);

Object dest映射后的类,Object orig映射前的类,name是属性名,value是属性的值

思考:

value是属性的值,那么判断value==null是否成立,然后成立不赋值,不成立将属性赋值

修改代码:

在这里插入图片描述

新建一个空白的maven项目(什么项目都可以)

从commons-beanutils-1.7.0-sources.jar中将BeanUtils.java和BeanUtilsBean.java复制过来(包名和原来一致)

maven项目中映入依赖commons-beanutils-1.7.0和commons-logging-1.1,不引入commons-logging-1.1,BeanUtilsBean.java汇报错,java文件找不到

BeanUtils.java

public static void copyProperties(Object dest, Object orig ,boolean inNull)
        throws IllegalAccessException, InvocationTargetException {

    BeanUtilsBean.getInstance().copyProperties(dest, orig , inNull);
}

新写入一个copyProperties方法,Object dest映射后对象,Object orig映射前对象,boolean inNull是否处理空对象,true(orig属性为空,dest属性为空),false(orig属性为空,dest属性为"")

BeanUtilsBean.java

public void copyProperties(Object dest, Object orig ,boolean isNull)
        throws IllegalAccessException, InvocationTargetException {

    // Validate existence of the specified beans
    if (dest == null) {
        throw new IllegalArgumentException
                ("No destination bean specified");
    }
    if (orig == null) {
        throw new IllegalArgumentException("No origin bean specified");
    }
    if (log.isDebugEnabled()) {
        log.debug("BeanUtils.copyProperties(" + dest + ", " +
                orig + ")");
    }

    // Copy the properties, converting as necessary
    if (orig instanceof DynaBean) {
        DynaProperty origDescriptors[] =
                ((DynaBean) orig).getDynaClass().getDynaProperties();
        for (int i = 0; i < origDescriptors.length; i++) {
            String name = origDescriptors[i].getName();
            if (getPropertyUtils().isWriteable(dest, name)) {
                Object value = ((DynaBean) orig).get(name);
                copyProperty(dest, name, value);
            }
        }
    } else if (orig instanceof Map) {
        Iterator names = ((Map) orig).keySet().iterator();
        while (names.hasNext()) {
            String name = (String) names.next();
            if (getPropertyUtils().isWriteable(dest, name)) {
                Object value = ((Map) orig).get(name);
                copyProperty(dest, name, value);
            }
        }
    } else /* if (orig is a standard JavaBean) */ {
        PropertyDescriptor origDescriptors[] =
                getPropertyUtils().getPropertyDescriptors(orig);
        for (int i = 0; i < origDescriptors.length; i++) {
            String name = origDescriptors[i].getName();
            if ("class".equals(name)) {
                continue; // No point in trying to set an object's class
            }
            if (getPropertyUtils().isReadable(orig, name) &&
                    getPropertyUtils().isWriteable(dest, name)) {
                try {
                    Object value =
                            getPropertyUtils().getSimpleProperty(orig, name);
                            //不同的地方
                    if (isNull){
                        //isNull为true
                        if (value==null) {
                            //value为null,不进行赋值操作
                            continue;
                        } else {
                            copyProperty(dest, name, value);
                        }
                    }else {
                        copyProperty(dest, name, value);
                    }
                } catch (NoSuchMethodException e) {
                    ; // Should not happen
                }
            }
        }
    }

}

在这里插入图片描述

编译代码修改jar包:

将编译后的BeanUtils.class和BeanUtilsBean.class复制到commons-beanutils-1.7.0.jar的指定包位置

代码运行执行就是新代码了

若idea报Library source does not match the bytecode for class这个错误

原因:idea自动反编译commons-beanutils-1.7.0.jar的代码,发现与commons-beanutils-1.7.0-sources.jar中的源码不同

解决方案:把BeanUtils.java和BeanUtilsBean.java复制到commons-beanutils-1.7.0-sources.jar的指定包位置

然后将idea中的缓存清除一下重新载入即可。

拿下拿下,完美收工!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值