1.概述
在項目中遇到要將數據庫對象轉換爲領域對象,不想一個個寫set(get()),也不想自己去寫反射,於是比較了一下開源的幾個工具類。個人瞭解的有apache的BeanUtils,PropertiesUitls,還有spring的BeanUtils。糾結於哪個更合適,於是比較了一下。
2.比較
apache PropertiesUtils | apache BeanUtils | spring BeanUtils | ||
實現複雜度 | 複雜 | 複雜 | 簡單 | |
功能特點 |
將源對象中和目標對象同名的屬性(淺拷貝),同名不同類 型拋異常(checked exception) |
同前,提供同名不同類型的 類型轉換並支持擴展 |
同PropertiesUtils | |
性能 |
3個屬性的對象,拷貝100w次 個人電腦2000ms |
5000ms | 600ms |
綜上所述,個人這個case是spring的BeanUtils更合適。apache的雖然更強大(考慮的細節和分支條件更多),
但暫時用不到,而且性能差距還是比較明顯。
對於轉換類爲map的describe方法,spring的Utils沒有,但很容易利用他現有方法擴展:
- public static Map<String, Object> describe(Object source) {
- Assert.notNull(source, "Source must not be null");
- HashMap<String, Object> result = new HashMap<String, Object>();
- Class<?> clazz = source.getClass();
- PropertyDescriptor[] sourcePds = BeanUtils.getPropertyDescriptors(clazz);
- for (int i = 0; i < sourcePds.length; i++) {
- PropertyDescriptor sourcePd = sourcePds[i];
- String name = sourcePd.getName();
- if (ignoreList.contains(name)) {
- continue;
- }
- try {
- Method readMethod = sourcePd.getReadMethod();
- if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
- readMethod.setAccessible(true);
- }
- Object value = readMethod.invoke(source, new Object[0]);
- result.put(name, value);
- } catch (Throwable e) {
- throw new FatalBeanException("Could not copy properties from source to HashMap", e);
- }
- }
- return result;
- }
3.總結
首先是否用反射來拷貝,本來就是在開發速度和運行速度之間的一個權衡。考慮到性能損耗在不大(對於本應用的性能需求來說),所以選擇用反射工具。
對於性能,spring比較快主要是因爲邏輯簡單些,而且緩存了BeanInfo信息,同樣的類不用每次都取。也算是空間換時間,當然更激進一點,可以像fastjson一樣,用字節碼方式把每個類型對生成一個拷貝類,時間上就和直接get,set差不多了。