Introspector
英译中为:内省
作用:一般在开发框架时,当需要操作一个JavaBean时,如果一直用反射来操作,显得很麻烦;所以sun公司开发一套API专门来用来操作JavaBean的属性,二者结合,干活不累。
何为bean:咖啡"爪哇"豆的别名,开个玩笑,其实就是一个Java类,我们天天都在使用。
我们定义一个实体对象类,封装一些属性:
Person.java
package com.appleyk.introspector;
public class Peroson {
private String name;
private String sex ;
private int age ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setAB(String ab){
}
public String getCD(){
return null;
}
}
除了我们定义的三个私有变量(name,sex,age)有特定的属性(getter 和 setter)外,我们又额外增加了两个"属性",一个是具有getter性质的函数getCD,一个是具有setter性质的setAB,ok,我们把Person类作为我们的测试JavaBean,暂时先放一放,我们开始介绍一下,本篇的主角Introspector,我们看下Java 1.8 API里面是怎么描述的:
Introspector类提供了一种标准的工具来了解目标Java Bean支持的属性,事件和方法。
API里我们继续翻找,找到了getBeanInfo方法的说明:
知道了类和对应的方法,我们现在来获得一下Person类的BeanInfo对象(对象里面的内容那是相当丰富!)
test.java:
package com.appleyk.introspector;
import java.beans.BeanInfo;
import java.beans.Introspector;
public class Test {
public static void main(String[] args) throws Exception{
BeanInfo beanInfo = Introspector.getBeanInfo(Peroson.class);
System.out.println(beanInfo);
}
}
我们看下打印这个beanInfo对象,输出的是什么:
我去,这什么鬼东西,看不懂啊? 没关系,好吧,我们不研究这个对象本身是什么,而是研究利用这个对象我们能干什么,我们继续:
上面我们说了 ,我们是来操作Bean属性的,现在Person的BeanInfo信息我们拿到了,我们接下来,就来看下怎么获得Person类中的属性数组,我们不得不说一个类PropertyDescriptor,看下API是怎么描述的:
ok,目前的问题是,怎么利用Person类的BeanInfo获得这个(这些)属性呢?我们再来看一下BeanInfo对象有哪些方法:
ok,一目了然,我们开始写代码测试:
测试前,思考一个问题,如果,用上述getPropertyDescriptors方法,得到Person Bean的属性数组,那么,问题来了,数组里会有几个属性呢? 3个?还是3+2=5个?还是其他答案呢?
Test.java:
package com.appleyk.introspector;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
public class Test {
public static void main(String[] args) throws Exception{
BeanInfo beanInfo = Introspector.getBeanInfo(Peroson.class);
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
for(PropertyDescriptor pd : pds){
System.out.println(pd.getName());
}
}
}
答案是3+2+1 = 6 个:
现在我们知道,Bean的属性,其实和Person类中定义了几个变量无关,而是和setter和getter有关,一对算作一个属性,如果落单的话,也算一个,因此,我们会看到,额外输出的属性名单中有我们的AB和CD:
但是这个属性是哪里冒出来的呢?
不卖关子了,所有类的基类(超类)都是Object,Person也不例外,我们看下,这个class属性是不是来自于Object,一样借助API:
我们怎么做到,从Person类的 BeanInfo对象中剔除掉基类的属性呢? 很简单,我们修改下getBeanInfo的参数调用:
上述的意思是,只得到Person类的BeanInfo,(stop)不要Object的BeanInfo
我们再来看下改后的执行效果(验证下):
上面说了怎么得到一个类的BeanInfo,以及怎么通过BeanInfo得到bean的属性数组,下面,我们通过demo来全篇演示一下如何操作Bean的属性:
放出demo之前,我们看下api中,关于属性类PropertyDescriptor的两个方法介绍:
getReadMethod :
getWriteMethod :
Test.java:
package com.appleyk.introspector;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception{
Peroson p = new Peroson();
BeanInfo beanInfo = Introspector.getBeanInfo(Peroson.class,Object.class);
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
System.out.println("----A、遍历Person Bean属性数组------------");
for(PropertyDescriptor pd : pds){
System.out.println(pd.getName());
}
System.out.println("----B、得到Person Bean的age属性------------");
//构造方法 PropertyDescriptor(String propertyName, 类<?> beanClass)
PropertyDescriptor pd =new PropertyDescriptor("age", Peroson.class);
System.out.println(pd.getName());
System.out.println("----C、得到Person Bean的age属性的类型------------");
System.out.println(pd.getPropertyType());
System.out.println("----D、给Person Bean的age属性赋值------------");
Method setter = pd.getWriteMethod();//得到写方法 即setter属性
setter.invoke(p, 26); //唤起(调用)Person对象p的age的setter属性 并赋值26
System.out.println("set age = 26");
System.out.println("----E、读取Person Bean的age属性------------");
Method getter = pd.getReadMethod(); //得到读方法 即getter属性
System.out.println("get age = "+getter.invoke(p)); //唤起(调用)Person对象p的age的getter属性 得到26
}
}
我们看下执行结果:
本篇结束。