BeanUtils的copyProperties,populate实现方式分析以及容易引发的Bug

BeanUtils的copyProperties方法用来将orig中的成员变量的值复制给dest,即将已经存在的dest变为orig的副本。

public void copyProperties(Object dest, Object orig) { 
....... 
}
 

BeanUtils的populate方法用来将Map<Key,value>中的以值(String或String[])转换到目标bean对应的属性中,Map中的Key是目标bean的属性名。

public static void populate(Object bean, Map properties){ 
…… 
}

copyProperties同样支持了populate中的功能(注apache的javadoc中,明确指明这个方法是为解析http请求参数特别定义和使用的,在正常的使用中不推荐使用.他们推荐使用BeanUtils.copyProperties方法)。

BeanUtils.copyProperties和populate的实现方法是将源bean(也可以是Map)中的每个element在转换器(Converter)的帮助下,将转换的结果设置到目标bean对应的属性中。例如在HTTP 应用中需要从http request中抽取数据,http request传递过来的都是String 或是String数组类型的变量而目标类型可能是各种各样的,例如http request会有一个name=visitDate,value=’2009-05-13′的参数,而目标bean 的visitDate属性的类型是java.util.Date。 
      BeanUtils的copyProperties和populate需要在转换器(converter)的配合下实现源和目标对象之间的数据类型的转换。在BeanUtils.copyProperties 的javadoc中说明的(Copy property values from the origin bean to the destination bean for all cases where the property names are the same—— 只要属性名相同就可以从源bean中拷贝值到目标bean中)这句话提供到功能就是要通过转换器才能实现的。在BeanUtils的 copyProperties和populate的使用过程中Converter是一个非常重要的概念,它提供了强大的扩展能力。

/****************************************************************/ 
public interface Converter { 
public Object convert(Class type, Object value); 

/****************************************************************/

convert方法的参数type是目标转换的类型,参数value是被转换的值,返回值就是转换以后的结果。当有需要自定义或扩展的Converter 的时候可以通过注册自定义的转换器来实现,例如Beanutil自带的DateConverter不支持String到java.util.Date的转换,通过扩展DateConverter就可以实现支持。需要特别注意的是Converter 是注册在classloader一级的,也就是说在一个class loader中同一时间只能有一个转换器起作用(BeanUtils的copyProperties和populate会依据目标bean属性的类型来决定启用那个转换器),我之前的项目中就有因为其他模块中在特定的时候会重新注册了某个类型的转换器,而新注册的转换器又没有支持我所需要的转换,从而导致在我的模块中出现NPE。 所以在使用BeanUtils.populate和copyProperties的时候要注意以下几点:

1. 只在系统初始化的时候注册一个转换器,而不要在某个功能的执行过程中注册转换器。 
2. 转换器要能够支持项目各个模块的使用需求 
3. 谨慎使用或者思考一下BeanUtils.populate和copyProperties是你想要的方法吗?

在我使用BeanUtils.populate的模块中本意是实现bean和Map的属性拷贝并不需要类型和值的转换。至于说为什么会使用 BeanUtils.populate完全是被它支持Map所误导,其实PropertyUtilsBean.copyProperties和 BeanUtils.copyProperties同样支持Map。就我想要实现的功能而言通过 PropertyUtilsBean.copyProperties方法能更好地满足。 PropertyUtilsBean.copyProperties方法不会有类型转换的逻辑,所以需要程序员自己保证目标和源Bean属性间的兼容性,也正因为如此PropertyUtilsBean.copyProperties的执行效率更高。

参考资料

BeanUtils.copyProperties与PropertyUtils.copyProperties用法及区别l

http://commons.apache.org/beanutils/v1.8.0/apidocs/org/apache/commons/beanutils/PropertyUtilsBean.html

http://commons.apache.org/beanutils/v1.8.0/apidocs/org/apache/commons/beanutils/BeanUtils.html

初用apache.commons.beanutils.BeanUtils

转自 http://www.daniel-journey.com/archives/72

原文地址:https://www.cnblogs.com/chenny3/p/10226228.html