一. JavaBean与内省的简介
JavaBean是一种特殊的类,凡是符合以下特点的类就可以被称作JavaBean:①该类中有一个无参的构造方法②对于这个类,有get和set方法用于访问其对应的值。
JavaBean是为了传递值而创建的,因此其对象也称之为值对象,而该类所对应的get和set方法,在get和set后的对应的是属性名,去掉get或者set后的属性名首字母是否大写要参照第二个字母是否大写,就是JavaBean的属性是通过get或者set方法推断出来的,无从获取到该方法对应哪个变量。
一个符合JavaBean特点的类可以当做普通类一样,但是作为JavaBean类肯定有额外的好处,在java中对JavaBean类专门提供了一套API,这套API就称为内省。内省与反射一样可以绕过对象,通过字节码来获取某个字段在某个对象上对应的值,但内省使用起来比反射要简便。
二. 内省的使用
1. PropertyDescriptor类
1> 构造方法
PropertyDescriptor(String “get或者set方法中的属性名”,Class该类字节码)
2> getReadMethod()
返回Method类型,也就是获取get方法
3> getWriteMethod()
返回Method类型,也就是获取set方法
2. Introspector类
1>getBeanInfo( Class JavaBean类的字节码)
该方法可以获得BeanInfo对象,也就是该类的属性信息,BeanInfo类中有一个方法叫做getPropertyDescriptors(),此方法可以返回全部的属性描述,他返回的是一个PropertyDescriptor数组,对这个数组进行遍历,获取某一个属性名。
演示一下这个两个类是怎样操作JavaBean的:
/*
* javaBean是指特殊的类,他的字段通过get和set方法可以获取修改,
* javaBean可以用来传递值,所以JavaBean类的对象可以称之为值对象。
*
* 而内省就是通过一些特定的类获取和修改属性值,类似于通过反射
* 的方式利用字节码文件来获取该字段在某一对象上的值,只不过内省的书写比反射
* 要简便,因为内省操作的字段对应的有get或者set方法。
* */
//首先写一个javaBean类
class Bean{
//定义私有变量
private Date date = new Date();
private int number;
//提供get和set方法
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
public class BeanDemo {
public static void main(String[] args) throws Exception{
Bean bean = new Bean();
//给定一个变量名称:number,根据该变量名称来操作属性值
String fieldName = "number";
/*
//如果利用反射的方式做:①获取字段法,如果不使用暴力反射就无法得到私有的属性
Class clsbean = Bean.class;
Field field = clsbean.getDeclaredField("number");
field.setAccessible(true);
field.set(bean, 100);
System.out.println(field.get(bean));
* //②通过方法获取,如果给定变量名称和bean类中的成员变量名不相同,getNumber方法的名字就需要推敲
* x--->X-->getX-->反射获取getX方法名
Method getme = clsbean.getMethod("getNumber", null);
System.out.println(getme.invoke(bean, null));*/
/*//利用PropertyDescriptor获取属性(简单):
PropertyDescriptor pd = new PropertyDescriptor("number", bean.getClass());
Method meGetnumber = pd.getReadMethod();
Object retval = meGetnumber.invoke(bean);
System.out.println(retval);
//修改属性值
Integer age = 12;
PropertyDescriptor pd = new PropertyDescriptor(fieldName, Obj.getClass());
Method meSetnumber = pd.getWriteMethod();
meSetnumber.invoke(bean, age);
System.out.println(bean.getNumber());*/
//利用Introspector获取类型(复杂型)
BeanInfo beans = Introspector.getBeanInfo(bean.getClass());
PropertyDescriptor[] pds = beans.getPropertyDescriptors();
for(PropertyDescriptor pd : pds)
{
if(pd.getName().equals(fieldName))
{
Method me = pd.getReadMethod();
System.out.println(me.invoke(bean, null));
break;
}
}
}
}
一. 内省工具包——BeanUtils
对于内省,有一些前辈们觉得以上的使用方法还是太麻烦就开发了一套工具包,专门用于内省操作,这个工具包就是BeanUtils,这个工具包必须配合另一个第三方工具包Logging来使用。
1. BeanUtils的常见方法
1> getProperty(Object bean,String name)
获取bean对象上该name所对应的值
2> setProperty(Object bean,String name,Object value)
为bean类的name属性设置值为value,这个value值以字符串代替即可,比如你输入“23”,他会自动把23转为Integer型。 name的值可以通过多层传递,比如有一个类叫做Date,他有一个字段名为time,对应set和get方法,在另一个JavaBean类当中,有一个属性为Date类型,而BeanUtils可以通过date属性拿到time:BeanUtils.getProperty(new Date(),“date.time”)
class Date
{
private int time;
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
}
class Test
{
private Date date = new Date();
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
1> describe(Object bean)
将对象中的属性和值转换成Map对象
2> populate(Object bean,Map properties)
将Map集合中的键值对填充给bean对象
1. BeanUtils与PropertyUtils
这两个类都具有setProperty方法,BeanUtils可以接收字符串,并将字符串转换为相应类型,而PropertyUtils只能接收相应的类型,而且getProperty()方法中,BeanUtils返回的属性值是String类型,而PropertyUtils方法返回的值原本是什么类型,现在便是什么类型。