Apache JakartaCommons項目非常有用。我曾在許多不同的項目上或直接或間接地使用各種流行的commons組件。其中的一個強大的組件就是BeanUtils。我將說明如何使用BeanUtils將local實體bean轉換為對應的value對象:
BeanUtils.copyProperties(aValue, aLocal)
上面的代碼從aLocal對象復制屬性到aValue對象。它相當簡單!它不管local(或對應的value)對象有多少個屬性,只管進行復制。我們假設local對象有100個屬性。上面的代碼使我們可以無需鍵入至少100行的冗長、容易出錯和反復的get和set方法調用。這太棒了!太強大了!太有用了!
現(xiàn)在,還有一個壞消息:使用BeanUtils的成本驚人地昂貴!我做了一個簡單的測試,BeanUtils所花費的時間要超過取數(shù)據(jù)、將其復制到對應的value對象(通過手動調用get和set方法),以及通過串行化將其返回到遠程的客戶機的時間總和。所以要小心使用這種威力!
Beanutils用了魔術般的反射技術,實現(xiàn)了很多夸張有用的功能,都是C/C++時代不敢想的。無論誰的項目,始終一天都會用得上它。我算是后知后覺了,第一回看到它的時候居然錯過。
1.屬性的動態(tài)getter,setter
在這框架滿天飛的年代,不能事事都保證執(zhí)行getter,setter函數(shù)了,有時候屬性是要需要根據(jù)名字動態(tài)取得的,就像這樣:BeanUtils.getProperty(myBean,"code");而BeanUtils更強的功能是直接訪問內嵌對象的屬性,只要使用點號分隔。
BeanUtils.getProperty(orderBean, "address.city");相比之下其他類庫的BeanUtils通常都很簡單,不能訪問內嵌的對象,所以經(jīng)常要用CommonsBeanUtils替換它們。
BeanUtils還支持List和Map類型的屬性。如下面的語法即可取得顧客列表中第一個顧客的名字
BeanUtils.getProperty(orderBean, "customers[1].name");其中BeanUtils會使用ConvertUtils類把字符串轉為Bean屬性的真正類型,方便從HttpServletRequest等對象中提取bean,或者把bean輸出到頁面。而PropertyUtils就會原色的保留Bean原來的類型。
2.beanCompartor 動態(tài)排序
還是通過反射,動態(tài)設定Bean按照哪個屬性來排序,而不再需要在bean的Compare接口進行復雜的條件判斷。List peoples = ...; // Person對象的列表Collections.sort(peoples, new BeanComparator("age"));如果要支持多個屬性的復合排序,如"Order By lastName,firstName"
ArrayList sortFields = new ArrayList();sortFields.add(new BeanComparator("lastName"));sortFields.add(new BeanComparator("firstName"));ComparatorChain multiSort = new ComparatorChain(sortFields);Collections.sort(rows,multiSort);其中ComparatorChain屬于jakata commons-collections包。
如果age屬性不是普通類型,構造函數(shù)需要再傳入一個comparator對象為age變量排序。
另外, BeanCompartor本身的ComparebleComparator, 遇到屬性為null就會拋出異常,也不能設定升序還是降序。
這個時候又要借助commons-collections包的ComparatorUtils.
Comparator mycmp =ComparableComparator.getInstance();
mycmp =ComparatorUtils.nullLowComparator(mycmp);//允許null
mycmp =ComparatorUtils.reversedComparator(mycmp); //逆序
Comparator cmp = newBeanComparator(sortColumn, mycmp);
3.Converter把Request或ResultSet中的字符串綁定到對象的屬性
經(jīng)常要從request,resultSet等對象取出值來賦入bean中,下面的代碼誰都寫膩了,如果不用MVC框架的綁定功能的話。
String a = request.getParameter("a"); bean.setA(a); String b = ....不妨寫一個Binder:
MyBean bean = ...; HashMap map = new HashMap(); Enumeration names = request.getParameterNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); map.put(name, request.getParameterValues(name)); } BeanUtils.populate(bean, map);其中BeanUtils的populate方法或者getProperty,setProperty方法其實都會調用convert進行轉換。
但Converter只支持一些基本的類型,甚至連java.util.Date類型也不支持。而且它比較笨的一個地方是當遇到不認識的類型時,居然會拋出異常來。
對于Date類型,我參考它的sqldate類型實現(xiàn)了一個Converter,而且添加了一個設置日期格式的函數(shù)。
要把這個Converter注冊,需要如下語句:
ConvertUtilsBean convertUtils = new ConvertUtilsBean();
DateConverter dateConverter = new DateConverter();
convertUtils.register(dateConverter,Date.class);
//因為要注冊converter,所以不能再使用BeanUtils的靜態(tài)方法了,必須創(chuàng)建BeanUtilsBean實例
BeanUtilsBean beanUtils = new BeanUtilsBean(convertUtils,new PropertyUtilsBean());
beanUtils.setProperty(bean, name, value);
4 其他功能
4.1 PropertyUtils,當屬性為Collection,Map時的動態(tài)讀?。?/strong>Collection: 提供indexBeanUtils.getIndexedProperty(orderBean,"items",1);或者
BeanUtils.getIndexedProperty(orderBean,"items[1]");
Map: 提供Key Value
BeanUtils.getMappedProperty(orderBean,"items","111");//key-value goods_no=111
或者
BeanUtils.getMappedProperty(orderBean,"items(111)")4.2 PropertyUtils,獲取屬性的Class類型
public static Class getPropertyType(Object bean, String name)4.3 ConstructorUtils,動態(tài)創(chuàng)建對象
public static Object invokeConstructor(Class klass, Object arg)
4.4 MethodUtils,動態(tài)調用方法
MethodUtils.invokeMethod(bean, methodName, parameter);4.5 動態(tài)Bean見用DynaBean減除不必要的VO和FormBean
一、概述
第一次看到BeanUtils包,是在Struts項目中,作為Struts一個工具來使用的,
估計功能越弄越強,就移到Common項目中了吧。
BeanUtils一共有四個package:
org.apache.commons.beanutils
org.apache.commons.beanutils.converters
org.apache.commons.beanutils.locale
org.apache.commons.beanutils.locale.converters
后三個包主要是用于數(shù)據(jù)的轉換,圍繞著一個Converter接口,該接口只有一個方法:
java.lang.Object convert(java.lang.Class type, java.lang.Objectvalue) ,
用于將一個value轉換成另一個類型為type的Object。在一些自動化的應用中應該會有用。
這里不作評論,以后有興趣了,或者覺得有用了,再行研究。
這里只講第一個包。
二、測試用的Bean
在開始所有的測試之前,我寫了一個簡單的Bean,以便于測試,代碼如下:
package test.jakarta.commons.beanutils;
public class Month {
private int value;
private String name;
private int[] days={11,22,33,44,55};
public Month(int v, String n){
value=v;
name=n;
}
public String getName() {
return name;
}
public int getValue() {
return value;
}
public void setName(String name) {
this.name = name;
}
public void setValue(int value) {
this.value = value;
}
public String toString() {
returnvalue+"("+name+")";
}
public int[] getDays() {
return days;
}
public void setDays(int[] is) {
days = is;
}
愛華網(wǎng)

