1、为什么要学内省(Introspector)?
开发框架时,经常需要使用Java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性,就是内省。2、这类Java对象有什么特点?
是一种特殊的Java类叫做JavaBean类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问,JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。去掉set和get前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。setId()的属性名->id
isLast()的属性名->last
setCPU的属性名是什么?->CPU
getUPS的属性名是什么->UPS
总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。
3、JavaBean类的优势
提高代码的可复用性:对于通用的事务处理逻辑,数据库操作(insert、delete、update、select等)都可以封装在JavaBean中,通过调用JavaBean的属性和方法可快速进行程序设计。4、内省的对JavaBean的操作
内省访问JavaBean属性的两种方式:通过PropertyDescriptor类操作Bean的属性
通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。
实例如下:
ReflectPoint pt1 = new ReflectPoint(3,5);
String propertyName = "x";
Object retVal = getProperty(pt1, propertyName);
System.out.println(retVal);
@Test
public void test() throws Exception{
Student stu=new Student();
// 1、通过Introspector类获得Bean对象的BeanInfo
BeanInfo entity=Introspector.getBeanInfo(Student.class);
// 2、然后通过 BeanInfo 来获取属性的描述器(PropertyDescriptor)
PropertyDescriptor pds[]= entity.getPropertyDescriptors();
// 3、通过这个属性描述器就可以获取某个属性对应的getter/setter方法
for(PropertyDescriptor pd:pds){
if(pd.equals("age")){ //age是什么类型?
//获取属性的类型
System.out.println(pd.getName()+""+pd.getPropertyType());
Method md=pd.getWriteMethod();
md.invoke(stu, 122);
break;
}
}
System.out.println(stu.getAge());
}
5、内省--Beanutils工具包
Sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils使用前提:引入beanutils包和logging包。
Beanutils工具包的常用类:
BeanUtils--get属性时返回的结果为字符串,set属性时可以接受任意类型的对象,通常使用字符串。
PropertyUtils--get属性时返回的结果为该属性本来的类型,set属性时只接受该属性本来的类型。
实例如下:
public void test1()throws Exception{
Class cls = Class.forName("cn.itcast.beanutils.Student");
Student bean = (Student)cls.newInstance();
BeanUtils.setProperty(bean, "name", "zhangxiaoxiang");
String name = BeanUtils.getProperty(bean, "name");
System.out.println(name);
BeanUtils.setProperty(bean, "age", "100");
String a = BeanUtils.getProperty(bean, "age");
System.out.println(a);
// birthday是Date类型的,Date类有setTime方法,所以支持级联操作
BeanUtils.setProperty(bean, "birthday.time", "1111");
System.out.println(bean.getAge());
System.out.println(bean.getName());
System.out.println(bean.getBirthday());
System.out.println(bean.getBirthday().getTime());
PropertyUtils.setProperty(bean, "age", 101);
System.out.println(PropertyUtils.getProperty(bean, "age"));
}