[学习笔记]Java内省机制(JavaBean)

概述

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); // 13
Object 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"); // 1419949175301
BeanUtils.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
}
 
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值