概述
1. 定义
- 内省(Introspector)是Java对Bean类属性、事件的一种缺省处理方法。给定一个javabean对象,我们就可以通过内省的方式得到/调用它的所有的get/set方法。
- JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有域,且方法名符合某种命名规则(例如标准的get/set方法)。如果在两个模块之间传递信息,可以将信息封装进JavaBean中,这种对象称为“值对象”(VO, Value Object),方法比较少。这些信息储存在类的私有变量中,通过set/get方法进行操作。
- 例如类A中有属性name, 那我们可以通过getName/setName来得到其值或者设置新的值,通过getName/setName这种方式来访问name字段,就是内省的默认规则。
- Java中提供了一套API用来访问某个属性的getter/setter方法,通过这些API可以使你不需要了解访问JavaBean私有域的方法就可以操作私有域,这些API存放于包java.beans中。
- 换言之,内省机制就是通过属性名来获取某JavaBean类的getter/setter方法,进一步通过该方法进行数据操作的机制。这里的属性名并非类的私有域名,而是取决于具体的getter/setter方法名。
例如对于私有域private String str; 如果对应的getter/setter方法为public String getName(),public void setName(String str)。那么属性名就是“name”,内省机制就是通过“name”获取到上述方法的Method实例,进一步就可以通过反射来操纵数据。
2. 类UML结构
3. 流程
- 通过类 Introspector 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。
- 更简单地,可以直接通过 PropertyDescriptor 的构造器,构造某个类的属性描述器,通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。
API
1. Introspector类
- 获取指定Bean类的BeanInfo实例
static BeanInfo getBeanInfo(Class<?> beanClass)
static BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass)
static BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass, int flags)
static BeanInfo getBeanInfo(Class<?> beanClass, int flags)
2. BeanInfo接口
- 获取该Bean类的方法属性描述器
MethodDescriptor[] getMethodDescriptors()
PropertyDescriptor[] getPropertyDescriptors()
3. MethodDescriptor类
构造器
- 通过方法直接构造方法描述器实例
MethodDescriptor(Method method)
MethodDescriptor(Method method, ParameterDescriptor[] parameterDescriptors)
方法
- 获取该方法描述器所对应的方法
Method getMethod() - 获取该方法描述器所对应的方法参数描述器
ParameterDescriptor[] getParameterDescriptors()
4. PropertyDescriptor类
构造器
- 通过Bean类字节码实例和属性名直接构造属性描述器实例
PropertyDescriptor(String propertyName, Class<?> beanClass)
PropertyDescriptor(String propertyName, Class<?> beanClass, String readMethodName, String writeMethodName)
PropertyDescriptor(String propertyName, Method readMethod, Method writeMethod)
方法
- 通过属性描述器获取该属性的getter/setter方法
Method getReadMethod()
Method getWriteMethod()
示例
Bean.java
package bean;import java.util.Date;public class Bean {private int i;private Date birth = new Date();public Bean(int i) {super();this.i = i;}public int getNum() {return i;}public void setNum(int i) {this.i = i;}public Date getBirth() {return birth;}public void setBirth(Date birth) {this.birth = birth;}}
IntrospectorDemo.java
package introspector;import java.beans.BeanInfo;import java.beans.IntrospectionException;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import bean.Bean;@SuppressWarnings("unused")public class IntrospectorDemo {public static void main(String[] args) throws Exception {Bean bean = new Bean(13);String propertyName = "num";// 通过内省获取该属性值Object value1 = getProperty1(bean, propertyName); // 13Object value2 = getProperty2(bean, propertyName); // 13// 通过内省设置该属性值setProperty(bean, propertyName, 22);System.out.println(bean.getNum()); // 22}/*** 通过Introspector获取指定属性描述器。** @param bean* @param propertyName* @return* @throws Exception*/private static Object getProperty1(Bean bean, String propertyName) throws Exception {// 使用Introspector获取Bean类的BeanInfo实例BeanInfo bi = Introspector.getBeanInfo(bean.getClass());// 使用BeanInfo获取Bean类的所有属性描述器PropertyDescriptor[] pds = bi.getPropertyDescriptors();for (PropertyDescriptor pd : pds) {// 找到指定的属性描述器if (pd.getName().equals(propertyName)) {// 获取该属性的get方法,并调用该方法获取属性值。Method method = pd.getReadMethod();Object value = method.invoke(bean);return value;}}return null;}/*** 通过PropertyDescriptor构造器构造实例,直接获取指定属性描述器。** @param bean* @param propertyName* @return* @throws Exception*/private static Object getProperty2(Bean bean, String propertyName) throws Exception {// 使用PropertyDescriptor构造器直接构造指定属性描述器。PropertyDescriptor pd = new PropertyDescriptor(propertyName, bean.getClass());// 获取该属性的get方法,并调用该方法获取属性值。Method method = pd.getReadMethod();Object value = method.invoke(bean);return value;}/*** 同样有两种方法设置属性值,这里通过PropertyDescriptor构造器构造实例,直接获取指定属性描述器。* @param bean* @param propertyName* @param i* @throws Exception*/private static void setProperty(Bean bean, String propertyName, int i) throws Exception {// 使用PropertyDescriptor构造器直接构造指定属性描述器。PropertyDescriptor pd = new PropertyDescriptor(propertyName, bean.getClass());// 获取该属性的set方法,并调用该方法获取属性值。Method method = pd.getWriteMethod();Object value = method.invoke(bean, i);}}
BeanUtils工具包
1. 概述
- Apache提供了一套方便操作JavaBean的工具包:BeanUtils工具包,工具包中的方法大多是静态的。
- BeanUtils类可以方便访问Bean类属性,并以字符串的方式进行处理,支持基本数据类型的转换。
- PropertyUtils类可以方便访问Bean类属性,与BeanUtils不同的是,他是以属性原类型的方式进行处理。
- BeanUtils工具包可以方便处理基本数据类型的属性,若非基本数据类型,则需要ConvetUtils包中的注册转换器进行转换。
- BeanUtils工具包支持属性的级联操作,例如:对Date类型属性中的Time属性进行操作。
- BeanUtils工具包可以方便地将Bean类属性信息与Map进行转换
2. 示例
package introspector;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.PropertyUtils;import bean.Bean;@SuppressWarnings("unused")public class BeanUtilsDemo {public static void main(String[] args) throws Exception {Bean bean = new Bean(22);String propertyName = "num";// 使用BeanUtils获取/设置属性值String property1 = BeanUtils.getProperty(bean, propertyName); // "22"BeanUtils.setProperty(bean, propertyName, "88" /*88*/);System.out.println(bean.getNum()); // 88// 使用BeanUtils获取/设置Bean中Bean属性值String property2 = BeanUtils.getProperty(bean, "birth.time"); // 1419949175301BeanUtils.setProperty(bean, "birth.time", "1000000000000");System.out.println(bean.getBirth()); // Sun Sep 09 09:46:40 CST 2001// 使用PropertyUtils获取/设置属性值Integer num = (Integer) PropertyUtils.getProperty(bean, propertyName); // 88}}
386

被折叠的 条评论
为什么被折叠?



