`

谈论 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反射中java.beans包学习总结.docx

    import java.beans.*; public class BeanConverter { public static &lt;T&gt; T convert(Map, String&gt; parameters, Class&lt;T&gt; clazz) throws Exception { T bean = clazz.getDeclaredConstructor().newInstance(); ...

    openbean.jar AndroidStudio 导入java.beans.*

    3. 在你的代码中,你可以通过`import java.beans.*;`引入所需类和接口。 使用`openbean.jar`和`java.beans`包可以帮助你在Android应用中实现一些高级功能,例如动态属性操作、事件处理和XML序列化。但是,需要注意...

    Java反射中java.beans包学习总结

    Java反射中java.beans包学习总结 Java反射中java.beans包是一个非常重要的包,提供了许多有用的工具类和接口,帮助我们更好地实现Java对象的反射操作。本篇文章将通过学习Java反射中java.beans包,总结出相关的知识...

    java.beans.*

    `java.beans.EventSetDescriptor` 描述了一个事件集,而 `java.beans.PropertyChangeEvent` 和 `java.beans.VetoableChangeEvent` 分别表示属性变化和可取消的变化事件。 4. **Listener**: 通过监听器接口,可以...

    org.springframework.beans-3.0.5工程所需jar包

    org.springframework.beans-3.0.5工程所需jar包,com.springsource.net.sf.cglib-2.2.0.jar、 com.springsource.org.apache.commons.logging-1.1.1.jar、 javax.inject.jar、 javax.servlet.jsp.jar、 org.spring...

    JAVA API官方中文版手册chm文件文档

    JAVA API官方文档中文版软件包 java.applet java.awt java.awt.color ...java.beans.beancontext java.io java.lang java.lang.annotation java.lang.instrument java.lang.management java.lang.ref

    org.springframework.beans-3.0.0.M4.jar

    org.springframework.beans-3.0.0.M4.jar

    org.springframework.beans.factory.config.PropertyPlaceholderConfigurer

    `org.springframework.beans.factory.config.PropertyPlaceholderConfigurer` 是Spring框架中的一个重要组件,主要负责处理配置文件中的占位符替换。这个类是Spring在初始化bean时用来解析和注入环境变量或系统属性...

    org.springframework.beans-3.0.0.CI-331.jar

    org.springframework.beans-3.0.0.CI-331.jar的jar包下载,请安心使用。

    JAVA_API1.8中文文档(CHM版).rar

    中文版,平时开发超...java.beans.beancontext 提供与 bean 上下文有关的类和接口。 java.io 通过数据流、序列化和文件系统提供系统输入和输出。 java.lang 提供利用 Java 编程语言进行程序设计的基础类。 ......

    org.springframework.beans-3.1.0.RELEASE.jar

    org.springframework.beans-3.1.0.RELEASE.jar

    JDK研究系列--》java.beans

    合适研究底层研发员,但,一般程序员也必须掌握的要点 JDK研究系列--java.beans

    Java反射技术浅谈.pdf

    反射技术在Java中的应用非常广泛,例如在Java Beans、Java Servlet、Java Server Page等技术中都使用了反射技术。反射技术还可以用于实现动态代理、Aspect-Oriented Programming等技术。 反射技术的实现是基于Java...

    lite-beans:LiteBeans是基于Apache Harmony项目的java.beans包的实现。

    由于它与AWT和Swing紧密依赖,因此无法轻易将其从java.desktop模块中删除,从而导致任何使用java.beans包的第三方库都依赖于所有java.desktop类。 java.desktop模块的额外开销使JVM安装增加了12mb的大小,并增加了...

    resolver_java_wsdl.jar

    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142) ... 38 more Caused by: java.lang.ClassNotFoundException: ...

    java-beans-lite:轻量级且快速的java.beans.Introspector实现

    轻巧,快速的java.beans.Introspector重新实现,用于消除对Bean Introspection的java.desktop模块的依赖。 问题 JDK 9中引入的模块封装了Java标准库中的所有AWT,Swing,Image和Sound软件包。 除此之外,它还包含带...

    JAVA_API1.6文档(中文)

    java.beans.beancontext 提供与 bean 上下文有关的类和接口。 java.io 通过数据流、序列化和文件系统提供系统输入和输出。 java.lang 提供利用 Java 编程语言进行程序设计的基础类。 java.lang.annotation 为 ...

    asm-3.2.3.jar

    org.springframework.beans.annotation org.springframework.beans.factory org.springframework.beans.factory.access org.springframework.beans.factory.access.el org.springframework.beans.factory.annotation...

    cglib-2.2.2.jar(修订版)

    at net.sf.cglib.beans.BeanCopier$Generator.generateClass(BeanCopier.java:133) at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) at ...

    java反射实现Object转json

    此外,Java标准库中的`java.beans.XMLEncoder`和`java.beans.XMLDecoder`也可以用来序列化和反序列化Java对象,但它们是针对XML的,而不是JSON。如果你需要处理JSON,还是要依赖第三方库。 总结起来,虽然Java反射...

Global site tag (gtag.js) - Google Analytics