May 22

误用jakata commons-beanutils引起bug分析

    项目里面大量的使用到了jakata的commin包,包括beanutils这个包,主要是用来copy bean property,以前一直用的很好,也没有去深究它内部的实现机制,评自己猜想就只是运用反射去取得属性的值,然后设置值吧。接着就出现了现在遇到的问题,项目中一个vo属性的类型为Byte包装类型,这种属性在实例化的时候默认为null,这个特性被我用到了业务中,也就是我会通过判断这个属性是否为null来实现某些逻辑,结果发现这个属性竟然会在没有任何人动的情况下自己被赋值为0,然后就导致依赖这个属性的业务逻辑错掉,debug一步一步的跟踪发现只要一经过beanutils,copy出来的bean的这个属性自动变为0了,以为是beanutils的bug,找来源码看了看,发现BeanUtils中其实是调用了BeanUtilsBean的copyProperties方法,BeanUtilsBean中实现了一个简单的工厂模式,将的一个实例绑定在当前线程中,有点儿类似ThreadLocal,也就是当前线程中所有调用都会采用同一机制进行copy,这里说到copy的机制其实就是指Converter,对于各种类型都有一个特定的Converter,包内部提供了一些jdk内部类型的Converter,每种类型Converter都有可以提供一种默认值,而在BeanUtils中对于Byte,Integer等数值类型提供的默认值是:0 ,所以就会出现把Byte类型值为null转换成了0。其实这么做也有他的好处,可以避免出现烦人的NullPointerExceprtion。知道原因,解决办法就很容易想到了,自己重新初始化一下BeanUtilBean中的ByteConverter。