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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章