谈论 Java反射与java.beans包

        这两天又看了看Rod Johnson的Expert one-on-one J2EE Without EJB。看到第七章是,看到bean属性动态赋值用到了java.beans.PropertyEditor觉得很想了解一下,于是通过重写一段原来的代码熟悉了java.beans API。感觉上这种实现方式规避了很多程序陷阱,而且可以让程序看起来更优雅。这里,我把重写的代码,跟对这种实现方式的看法表达出来。
 
       首先说说需求。
根据类名生成一个实例我们现在叫他obj,一个Map(map中存储的是property key-value),把Map的值根据obj的property name赋给obj。
例如,obj有name,age两个属性并且曝露Javabean标准的存取属性的方法,map有 name=lh , age=11 两个键值对。

       分析一下我们要做什么。
              1,首先根据反射找出所有公开的存取方法,通过方法名跟map的key进行匹配,找出keyName。找出需要赋值的方法setMethod
              2,根据setMethod的方法签名,找到接收参数的类型class.
              3,把keyName的值keyValue得到,把keyValue转变成class类型。
              4,调用setMethod。    

下面是一段类型转换的代码。
static Object getValue(Object v, Class type) {
        if (type.getName().equals(String.class.getName())) {
            return v.toString();
        } else if (type.getName().equals(Long.class.getName())) {
            return new Long(v.toString());
        } else if (type.getName().equals(Integer.class.getName())) {
            return new Integer(v.toString());
        } else if (type.getName().equals(Double.class.getName())) {
            return new Double(v.toString());
        } else if (type.getName().equals(Date.class.getName())) {
            return java.sql.Date.valueOf(v.toString());
        } else if (type.getName().equals(long.class.getName())) {
            return new Long(v.toString());
        } else if (type.getName().equals(int.class.getName())) {
            return new Integer(v.toString());
        } else if (type.getName().equals(double.class.getName())) {
            return new Double(v.toString());
        }else if (type.getName().equals(BigDecimal.class.getName())) {
            return new BigDecimal(v.toString());
        } else {

            return null;
        }
    }


这段代码的问题一目了然,每加入一个需要转换的类型就要修改这段代码,但是通过用java.beans API可以解决这个问题。
package com.surekam.util.reflection;

import java.beans.BeanInfo;
import java.beans.Expression;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.lang.reflect.Method;
import java.util.Properties;

import com.surekam.model.record.TobacOrder;

import test.util.TestXML;

/**
 * 类说明:通过反射为bean赋值。
 * 
 * @author 李华
 * 
 */
 
 //
public class Evaluate { /** * 参数说明:*className :要赋值的bean的type**po:要赋值的bean,如果po为空则创建一个**prop:属性名->值** @author 李华 * */  
    public static Object evaluatePo(String className, Object po, Properties prop) {
        try {

            Class poClass = Class.forName(className);

            if (po == null) {
                po = poClass.newInstance();
            }
 // Introspector相当beans这个架构的一个入口。类似于Hibernate的SessionFactory// 通过bean的类型获得bean的描述—》获得属性描述的集合
            BeanInfo bi = Introspector.getBeanInfo(poClass);
            PropertyDescriptor[] pd = bi.getPropertyDescriptors();

            for (int i = 0; i < pd.length; i++) {
                if (prop.getProperty(pd[i].getName()) != null) {
                    Object value = getPropValue(pd[i].getPropertyType(),
                            prop.getProperty(pd[i].getName()));

                    executeEvaluate(po, pd[i].getWriteMethod(), value);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return po;
    }
    
    // 这里是PropertyEditor 的使用,规避了if条件的使用。让代码的扩展性得到了很好的保证。这里使用的是依赖查找(DL)的方式。// 注册PropertyEditor 的步骤放在了bean容器当中    static Object getPropValue(Class clazz, String value)
            throws InstantiationException, IllegalAccessException {
        PropertyEditor pe = PropertyEditorManager.findEditor(clazz);
        pe.setAsText(value);
        return pe.getValue();
    }

    //调用赋值方法
    static void executeEvaluate(Object dest, Method m, Object value)
            throws Exception {
        Expression e = new Expression(dest, m.getName(),
                new Object[] { value });
        e.execute();
    }   

}  
 
总结一下PropertyEditor 的使用方式。    1,注册PropertyEditor 。通过PropertyEditorManager的registerEditor方法注册PropertyEditor。    2,查找PropertyEditor 。通过PropertyEditorManager的findEditor方法查找PropertyEditor。    3,转换值。调用PropertyEditor 的setAsText方法进行转换。用getValue方法获得值。  java.beans包是JDK对java reflection的封装。Expression 封装了方法调用的细节。BeanInfo ,PropertyDescriptor封装了查找属性的细节。规避了很多代码的陷阱,隐藏了很多reflection的实现细节。通过这个框架编写的代码,更加强壮,更加有扩展性。

你可能感兴趣的:(java,sql,bean,Hibernate,ejb)