Struts中Form2Bean的两种reflect机制 以及性能对比

来源:互联网 发布:深圳经纬之创网络 编辑:程序博客网 时间:2024/06/08 15:12

在用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就可以执行完?

还是我的测试方法有问题?各位一起探讨一下吧

原创粉丝点击