`
dengminhui
  • 浏览: 164083 次
  • 来自: ...
社区版块
存档分类
最新评论

Introspector(内省)学习

阅读更多

      反射比内省更容易理解一点。用一句比较白的话来概括,反射就是让你可以通过名称来得到对象 ( 类,属性,方法 ) 的技术,这种技术比内省机制使用范围更广泛。例如我们可以通过类名来生成一个类的实例;知道了方法名,就可以调用这个方法;知道了属性名就可以访问这个属性的值。

      内省是 Java 语言对 Bean 类属性、事件的一种缺省处理方法。例如类 A 中有属性 name, 那我们可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。 Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则(但你最好还是要搞清楚),这些 API 存放于包 java.beans 中。
      一般的做法是通过类 Introspector 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。

    以下是BeanInfo的源代码,其中getMethodDescriptors,getPropertyDescriptors,getEventSetDescriptors分别用来取得素有的方法,变量,事件。

 

/*
 * @(#)BeanInfo.java	1.28 03/12/19
 *
 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package java.beans;

/**
 * A bean implementor who wishes to provide explicit information about
 * their bean may provide a BeanInfo class that implements this BeanInfo
 * interface and provides explicit information about the methods,
 * properties, events, etc, of their  bean.
 * <p>
 * A bean implementor doesn't need to provide a complete set of
 * explicit information.  You can pick and choose which information
 * you want to provide and the rest will be obtained by automatic
 * analysis using low-level reflection of the bean classes' methods
 * and applying standard design patterns.
 * <p>
 * You get the opportunity to provide lots and lots of different
 * information as part of the various XyZDescriptor classes.  But
 * don't panic, you only really need to provide the minimal core
 * information required by the various constructors.
 * <P>
 * See also the SimpleBeanInfo class which provides a convenient
 * "noop" base class for BeanInfo classes, which you can override
 * for those specific places where you want to return explicit info.
 * <P>
 * To learn about all the behaviour of a bean see the Introspector class.
 */

public interface BeanInfo {

    /**
     * Gets the beans <code>BeanDescriptor</code>.
     * 
     * @return  A BeanDescriptor providing overall information about
     * the bean, such as its displayName, its customizer, etc.  May
     * return null if the information should be obtained by automatic
     * analysis.
     */
    BeanDescriptor getBeanDescriptor();
    
    /**
     * Gets the beans <code>EventSetDescriptor</code>s.
     * 
     * @return  An array of EventSetDescriptors describing the kinds of 
     * events fired by this bean.  May return null if the information
     * should be obtained by automatic analysis.
     */
    EventSetDescriptor[] getEventSetDescriptors();

    /**
     * A bean may have a "default" event that is the event that will
     * mostly commonly be used by humans when using the bean. 
     * @return Index of default event in the EventSetDescriptor array
     *		returned by getEventSetDescriptors.
     * <P>	Returns -1 if there is no default event.
     */
    int getDefaultEventIndex();

    /**
     * Gets the beans <code>PropertyDescriptor</code>s.
     * 
     * @return An array of PropertyDescriptors describing the editable
     * properties supported by this bean.  May return null if the
     * information should be obtained by automatic analysis.
     * <p>
     * If a property is indexed, then its entry in the result array will
     * belong to the IndexedPropertyDescriptor subclass of PropertyDescriptor.
     * A client of getPropertyDescriptors can use "instanceof" to check
     * if a given PropertyDescriptor is an IndexedPropertyDescriptor.
     */
    PropertyDescriptor[] getPropertyDescriptors();

    /**
     * A bean may have a "default" property that is the property that will
     * mostly commonly be initially chosen for update by human's who are 
     * customizing the bean.
     * @return  Index of default property in the PropertyDescriptor array
     * 		returned by getPropertyDescriptors.
     * <P>	Returns -1 if there is no default property.
     */
    int getDefaultPropertyIndex();

    /**
     * Gets the beans <code>MethodDescriptor</code>s.
     * 
     * @return An array of MethodDescriptors describing the externally
     * visible methods supported by this bean.  May return null if
     * the information should be obtained by automatic analysis.
     */
    MethodDescriptor[] getMethodDescriptors();

    /**
     * This method allows a BeanInfo object to return an arbitrary collection
     * of other BeanInfo objects that provide additional information on the
     * current bean.
     * <P>
     * If there are conflicts or overlaps between the information provided
     * by different BeanInfo objects, then the current BeanInfo takes precedence
     * over the getAdditionalBeanInfo objects, and later elements in the array
     * take precedence over earlier ones.
     *
     * @return an array of BeanInfo objects.  May return null.
     */
    BeanInfo[] getAdditionalBeanInfo();

    /**
     * This method returns an image object that can be used to
     * represent the bean in toolboxes, toolbars, etc.   Icon images
     * will typically be GIFs, but may in future include other formats.
     * <p>
     * Beans aren't required to provide icons and may return null from
     * this method.
     * <p>
     * There are four possible flavors of icons (16x16 color,
     * 32x32 color, 16x16 mono, 32x32 mono).  If a bean choses to only
     * support a single icon we recommend supporting 16x16 color.
     * <p>
     * We recommend that icons have a "transparent" background
     * so they can be rendered onto an existing background.
     *
     * @param  iconKind  The kind of icon requested.  This should be
     *    one of the constant values ICON_COLOR_16x16, ICON_COLOR_32x32, 
     *    ICON_MONO_16x16, or ICON_MONO_32x32.
     * @return  An image object representing the requested icon.  May
     *    return null if no suitable icon is available.
     */
    java.awt.Image getIcon(int iconKind);
     
    /**
     * Constant to indicate a 16 x 16 color icon.
     */
    final static int ICON_COLOR_16x16 = 1;

    /**
     * Constant to indicate a 32 x 32 color icon.
     */
    final static int ICON_COLOR_32x32 = 2;

    /**
     * Constant to indicate a 16 x 16 monochrome icon.
     */
    final static int ICON_MONO_16x16 = 3;

    /**
     * Constant to indicate a 32 x 32 monochrome icon.
     */
    final static int ICON_MONO_32x32 = 4;
}

 

 

一般来说,我们还可以使用Map和内省机制来构造一个Bean的实例对象,实例代码如下:

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.HashMap;
import java.util.Map;
import java.lang.reflect.InvocationTargetException;

public class MapToBean {

    public static void main(String[] args) throws Exception {
        Map<Object, Object> map = new HashMap<Object, Object>();
        map.put("name", "张三");
        map.put("age", 30);
        Person p = convertMap(Person.class, map);
        System.out.println(p.getName() + "," + p.getAge());
    }

    /**
     *将一个Map对象转化为一个JavaBean
     * 
     *@param type要转化的类型
     *@param map 包含属性值的map
     * @return转化出来的JavaBean对象
     * @throwsIntrospectionException  如果分析类属性失败
     *@throwsIllegalAccessException  如果实例化JavaBean失败
     *@throwsInstantiationException  如果实例化JavaBean失败
     *@throwsInvocationTargetException如果调用属性的setter方法失败  
     */
    private static<T> T convertMap(Class<T> type, Map<Object, Object> map) throws IntrospectionException,
                                                                           IllegalAccessException,
                                                                           InstantiationException,
                                                                           InvocationTargetException {
        BeanInfo beanInfo = Introspector.getBeanInfo(type);// 获取类属性  
        T t = type.newInstance();// 创建JavaBean对象  
        // 给JavaBean对象的属性赋值
        for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) {
            String propertyName = descriptor.getName();
            if (map.containsKey(propertyName)) {
                // 下面一句可以try起来,这样当一个属性赋值失败的时候就不会影响其他属性赋值。  
                descriptor.getWriteMethod().invoke(t, map.get(propertyName));
            }
        }
        return t;
    }
}

class Person {

    private String name;
    private int    age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

 

 

参考地址:http://yangzhibin-java.iteye.com/blog/452068

 

1
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics