在用Struts开发时,在Web层需要一个FormBean,在Model层又需要一个ModelBean,而这两个Bean几乎是一模一样的(FormBean中可能会有一些界面控制的隐含域属性),起码ModelBean所需要的数据在FormBean中全部都有。
在编程中,需要将FormBean的值传递给ModelBean,通常需要用很多的:
ModelBean.setXxx(FormBean.getXxx());
烦不胜烦。 利用java的reflect机制可以偷个懒,但是偷懒归偷懒,不能忽略了性能。
下面就是用两种不同的算法实现的FormBean→ModelBean的方法,其性能差距是比较大的,而且Bean的属性越多,这种差距就越大。代码如下:
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;

import com.perspace.model.Relation;
import com.perspace.struts.form.RelationForm;


public class BeanUtil ...{

/** *//**
* @parameter Object obj1,Object obj2
* @return Object 用到反射机制 此方法将调用obj1的getter方法,将得到的值作为相应的参数传给obj2的setter方法
* 注意,obj1的getter方法和obj2方法必须是public类型
*/

public static Object duplicateBeans(Object obj1, Object obj2)

throws Exception ...{

Method[] method1 = obj1.getClass().getMethods();
Method[] method2 = obj2.getClass().getMethods();
String methodName1;
String propertyName1;
String methodName2;
String propertyName2;

for (int i = 0; i < method1.length; i++) ...{
methodName1 = method1[i].getName();
propertyName1 = methodName1.substring(3, methodName1.length());

if (methodName1.startsWith("get")) ...{

for (int j = 0; j < method2.length; j++) ...{
methodName2 = method2[j].getName();
propertyName2 = methodName2.substring(3, methodName2
.length());

if (methodName2.startsWith("set")) ...{

if (propertyName2.equals(propertyName1)) ...{
Object[] objs1 = new Object[0];
Object[] objs2 = new Object[1];
// 激活obj1的相应的get的方法,objs1数组存放调用该方法的参数,此例中没有参数,该数组的长度为0
objs2[0] = method1[i].invoke(obj1, objs1);
// 激活obj2的相应的set的方法,objs2数组存放调用该方法的参数
method2[j].invoke(obj2, objs2);
continue;
}
}
}
}
}
return obj2;
}


/** *//**
* do the following things: bean2.setXxx(bean1.getXxx());
* Note:
* bean1 maybe have more properties than bean2, bean2 gets all values if bean1 has.
* @param bean1
* @param bean2
* @return
*/
public static Object duplicateBean2(Object bean1, Object bean2)

throws Exception ...{
Method[] method1 = bean1.getClass().getMethods();
Method[] method2 = bean2.getClass().getMethods();
HashMap map1 = new HashMap();
HashMap map2 = new HashMap();
String methodName;
String propertyName;

for (int i = 0; i < method1.length; i++) ...{
methodName = method1[i].getName();

if (methodName.startsWith("get")) ...{
propertyName = methodName.substring(3, methodName.length());
map1.put(propertyName, methodName);
}
}

for (int i = 0; i < method2.length; i++) ...{
methodName = method2[i].getName();

if (methodName.startsWith("set")) ...{
propertyName = methodName.substring(3, methodName.length());
map2.put(propertyName, methodName);
}
}
int propertyCount = map2.size();
String key;
Object getterMethod;
Iterator iterator = map2.keySet().iterator();

while (iterator.hasNext())...{
key = (String)iterator.next();
getterMethod = map1.get(key);

if (getterMethod != null)...{
Object[] objs1 = new Object[0];
Object[] objs2 = new Object[1];
// 激活obj1的相应的get的方法,objs1数组存放调用该方法的参数,此例中没有参数,该数组的长度为0
objs2[0] = bean1.getClass().getMethod(((String)getterMethod), null).invoke(bean1, objs1);
// 激活obj2的相应的set的方法,objs2数组存放调用该方法的参数
bean2.getClass().getMethod((String)map2.get(key), String.class).invoke(bean2, objs2);
}
}
return bean2;
}

public static void main(String[] args)...{
RelationForm rf = new RelationForm();
Relation r = new Relation();
Relation r1 = new Relation();
rf.setId("2342342342342342");
rf.setId1("11111111111111");
rf.setId2("22222222222222222");
rf.setType("type");
rf.setGrade("grade");
rf.setDate("date");
rf.setNote("note");

try...{
long begin = System.currentTimeMillis();
r = (Relation)BeanUtil.duplicateBeans(rf, r);
long end = System.currentTimeMillis();
System.out.println("first run:" + (end -begin));
long begin1 = System.currentTimeMillis();
r1 = (Relation)BeanUtil.duplicateBean2(rf, r1);
long end1 = System.currentTimeMillis();
System.out.println("second run:" + (end1 -begin1));

}catch(Exception e)...{
e.printStackTrace();
}
System.out.println(r.getId() + ":" + r.getId1() + ":" + r.getId2() + ":" + r.getType() + ":" + r.getGrade() + ":" + r.getDate() + ":" + r.getNote());
}
}

执行结果如下:
first run:15
second run:0
2342342342342342:11111111111111:22222222222222222:type:grade:date:note
可见,第二种算法比第一种算法要优化很多。在Struts大量做form2Model的环境中,这种点滴的积累还是很可观的。
另外:优化归优化,但是一直这个second run=0的结果让我十分不解,难道性能真的好的不到一个milli second就可以执行完?
还是我的测试方法有问题?各位一起探讨一下吧