java的内省(introspector)

java的内省相当于反射的一个特例,他专门用来操作java的Bean对象的属性。

在“容器的应用”笔记里,我们已经了解了javaBean是什么,首先我们再来学习什么是javaBean的属性:

一个类,里面有自己的private字段,只能叫做字段,如果他对外提供了set或get方法,他才能叫做属性。也就是说,javaBean的属性是由set和get方法决定是不是有这个属性的,而不是由这个类里面的字段决定的。

举个例子,在一个叫做Person的javaBean里,没有nation这个字段,但我们提供了一个方法:

 public String getNation() {
       return null;
 }

这样,这个javaBean对外就拥有nation这个属性,虽然为null。

而且,如果再加入另一个一模一样的get方法:

 public String getNation() {
       return null;
 }

这样,这个javaBean对外就又有了另外一个属性。

接下来我们就来了解内省类:

我们用Person这个javaBean来做内省测试的来源,person类的代码如下:

public class Person {
     private String name;
     private String ID;
     private int age;
     public String getNation() {
           return null;
     }
     public String getName() {
           return name;
     }
     public void setName(String name) {
           this.name = name;
     }
     public String getID() {
           return ID;
     }
     public void setID(String iD) {
           ID = iD;
     }
     public int getAge() {
           return age;
     }
     public void setAge(int age) {
           this.age = age;
     }
}

内省的核心api就是Introspector类,这个类里有一个getBeanInfo方法,可以内省javaBean并了解他的所有属性,暴露的方法和事件,内省完成,封装起来返回值就是一个BeanInfo对象。

那么拿到的属性,这个BeanInfo对象里,有对应的方法,比如getPropertyDescriptors(),就可以获取每一个属性的属性描述器,返回值就是一个PropertyDescriptor[]这样一个数组,里面就是保存着属性的描述。

进而,PropertyDescriptor类里有对应的:getReadMethod()方法和getWriteMethod()方法,可以获取到应该用于读和写属性值的方法,返回值是一个Method,也就是获得到get和set方法。

针对上面创建好的javaBean,我们写测试类来测试内省

 @Test
 public void test1() throws Exception {
       //用getBeanInfo方法获得一个JavaBean的BeanInfo,参数是一个Bean类
       BeanInfo info=Introspector.getBeanInfo(Person.class);
       //接着调用getPropertyDescriptors获取所有属性描述器
       //返回值是数组,获取了所有属性描述器,要到具体的某一个需要for循环
       PropertyDescriptor[]  descriptors=info.getPropertyDescriptors();
       //先用getName输出所有的属性名
       for(PropertyDescriptor des:descriptors) {
            System.out.println(des.getName());
       }
 }

可以看到输出结果:

在这里插入图片描述

对比上面的JavaBean类Person,可以看到确实属性的个数是由set和get方法决定的,因为确实getName到了一个nation属性。

同时我们也发现,多出了一个class属性,这是什么呢,是从父类Object类里继承来的一个属性,虽然我们并没有写。如果想要得到的属性描述器只有我们自己写进去的,可以这样进行操作:

我们打开getPropertyDescriptors方法的源码,可以看到有很多重载的方法,里面有这样一个:

public static BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass)

输入两个参数的时候,可以有一个stop的Class,我们stop掉父类Object的BeanInfo:

       BeanInfo  info=Introspector.getBeanInfo(Person.class,Object.class);

然后重新运行一下这个测试方法:

在这里插入图片描述

可以看到只剩下我们自己写进这个Bean类里的四个属性了。

接下来我们对获取到的属性进行操作,在上面我们用getPropertyDescriptors方法,获取到的是所有属性包含在内的一个PropertyDescriptor数组,但是如果我们已经知道了里面有哪些属性,可以针对具体的一个属性进行操作,我们只用创建一个新的PropertyDescriptor对象,用构造器传入对应的参数包括属性名和Bean类:

       PropertyDescriptor descriptors=new  PropertyDescriptor("age", Person.class);

然后我们就可以获得对应的写方法或者读方法,我们针对age属性获得写方法为例:

       Method method=descriptors.getWriteMethod();

接着invoke调用一下这个方法(因为invoke的参数里要针对一个对象调用,我们要new一个Bean对象):

       Person person=new Person();
       method.invoke(person, 22);

这时候已经成功内省了个属性的写set方法,然后我们输出看看是不是写进去了:

       System.out.println(person.getAge());

此时测试就会输出结果是22.

同理,对于get方法,我们也可以通过内省来获得,然后用invoke调用,下一个测试方法以属性name为例:

 @Test
 public void test3() throws Exception {
       BeanInfo  info=Introspector.getBeanInfo(Person.class,Object.class);
       PropertyDescriptor descriptors=new  PropertyDescriptor("name", Person.class);
       //接着获得对应的 写 方法 ,和 读 方法
       Method method=descriptors.getWriteMethod();
       Method method2=descriptors.getReadMethod();
       Person person=new Person();
       method.invoke(person, "john");
       //把get方法也进行引用
       System.out.println(method2.invoke(person, null));
 }

同样,像反射的时候我们可以获得某个方法的返回值的类型,在内省的时候也一样可以获得这个属性的类型:

 @Test
 public void test4() throws Exception {
       BeanInfo  info=Introspector.getBeanInfo(Person.class,Object.class);
       PropertyDescriptor descriptors=new  PropertyDescriptor("name", Person.class);
       //getPropertyType方法获得这个属性的类型
       System.out.println(descriptors.getPropertyType());
 }

这个测试方法输出结果就是,这个name属性的类型:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值