欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JAVA重写copyProperties,使其支持Map类型 博客分类: Java  

程序员文章站 2024-03-16 12:12:16
...

BeanUtils和PropertyUtils类是许多开源框架中频繁使用的两个工具,它们都能实现将一个类中的属性拷贝到另一个类中,这个功能甚至是spring实现依赖注入的基础。研究一下apache的comon包中如何实现这个两个工具,可以发现它们都是使用java.lang.reflect和java.beans这两个包下的几个类来实现的。

    但是BeanUtils.copyProperties只支持两个对象之间的复制,其原理:是利用反射读取到第一个对象(源类)的所有属性,然后对这些属性集合进行for循环,再在for循环里面判断这些属性是否有set方法,有则再对第二个对象(目标类)进行循环取出属性一一对比,相等则调用目标类的set方法得到源类的get方法得到的值。

    改后主要就是两点:第一:源类(Map类型)的Key作为属性和目标类的属性对比,相等则取出此Key的Value赋给目标类(当然还是用目标类此属性的set方法)。注意:如果是通过http请求的getParameterMap()得到的Map,其值是一个数组,一般只需要取第0项就可以了。

 

    /** 
     * 实现将源类(Map类型)属性拷贝到目标类中
     * @param Map map  源Map对象
     * @param Object obj  目标对象
     */
    public static void copyProperties(Map map, Object obj) throws Exception
    {
        // 获取目标类的属性信息
        BeanInfo targetbean = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = targetbean.getPropertyDescriptors();
        // 对每个目标类的属性查找set方法,并进行处理
        for (int i = 0; i < propertyDescriptors.length; i++)
        {
            PropertyDescriptor pro = propertyDescriptors[i];
            Method wm = pro.getWriteMethod();

            if (wm != null)
            {
                Iterator ite = map.keySet().iterator();
                while (ite.hasNext())
                {
                    String key = (String) ite.next();
                    // 判断匹配
                    if (key.toLowerCase().equals(pro.getName().toLowerCase()))
                    {
                        if (!Modifier.isPublic(wm.getDeclaringClass().getModifiers()))
                        {
                            wm.setAccessible(true);
                        }

                        Object value = ((String[]) map.get(key))[0];
                        String pt = splitSpace(pro.getPropertyType().getName());

                        // 判断类型是否匹配,不匹配则作强制转换
                        if (!(pt.equals(value.getClass().getName())))
                        {
                            value = parseByType(pro.getPropertyType(), value.toString());
                        }

                        // 调用目标类对应属性的set方法对该属性进行填充
                        wm.invoke((Object) obj, new Object[] { value });
                        break;
                    }
                }
            }
        }
    }