Java 内省机制
内省(introspector)这个词,就翻译上来说,还真是不太好理解,也不太好意译,总之我觉得只要把它当作是一种约定俗成的叫法就好,更重要的是理解它的实现机制。
1. JavaBean
JavaBean是内省机制中重要的一员,它是内省机制操作的对象,它也是Java类,只是遵循了某种约定写法的Java类,它里面包含了私有的(private)的属性及这些属性对应的Setter和Getter方法,它对数据进行了封装,对应了一定的业务逻辑;JavaBean和POJO(PlainOrdinary Java Object,即简单的Java对象)很像,但又不完全一样。例如下面一个类就是一个JavaBean:
package learn.introspector;
public class Person {
private String name;
private int age;
private String ID;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
}
这个类并没有实现任何的额外功能,知识对其内部的成员进行了一些简单的操作,我们把符合这个规范的类就叫做JavaBean。
2. 内省机制包含的类
1) 既然内省是对JavaBean的操作,那肯定有对应JavaBean属性的类,它就是属性描述器(PropertyDescriptor),它通常会和反射机制一同使用。
2) Introspector类,它可以把一个类看作是JavaBean,通过getBeanInfo()方法获得这个类的信息。
通过以上两种都可以获得JavaBean的信息,上面的描述可能不是特别好理解,还是来看一下代码比较好理解:
通过PropertyDescriptor类:
package learn.introspector;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Person类
* JavaBean
*/
class Person {
private String name;
private int age;
private String ID;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
}
public class IntrospectorDemo{
/**测试
* @throws IntrospectionException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException */
public static void main(String args[]) throws IntrospectionException,IllegalAccessException, IllegalArgumentException, InvocationTargetException {
/*创建JavaBean实例,并赋值*/
Person person=new Person();
person.setName("李明");
person.setAge(15);
person.setID("1");
/*创建name属性描述器*/
PropertyDescriptor propertyDescriptor=new PropertyDescriptor("name", person.getClass());
/*获得person的getName()方法的Method对象*/
Method methodGetName=propertyDescriptor.getReadMethod();
/*打印mathodGetName的调用结果,相当于执行了person的getName()方法*/
System.out.println(methodGetName.invoke(person));
/*获得person的setName()方法的Method对象*/
Method methodSetName=propertyDescriptor.getWriteMethod();
/*打印mathodSetName的调用结果,相当于执行了person的setName()方法*/
methodSetName.invoke(person, "王五");
System.out.println(methodGetName.invoke(person));
}
}
通过Introspector类:
package learn.introspector;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
importjava.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
*Person类
*JavaBean
*/
class Person {
privateString name;
privateint age;
privateString ID;
publicString getName() {
returnname;
}
publicvoid setName(String name) {
this.name= name;
}
publicint getAge() {
returnage;
}
publicvoid setAge(int age) {
this.age= age;
}
publicString getID() {
returnID;
}
publicvoid setID(String ID) {
this.ID= ID;
}
}
public class IntrospectorDemo{
/**测试
* @throws IntrospectionException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException */
publicstatic void main(String args[]) throws IntrospectionException,IllegalAccessException, IllegalArgumentException, InvocationTargetException {
/*创建JavaBean实例,并赋值*/
Personperson=new Person();
person.setName("李明");
person.setAge(15);
person.setID("1");
BeanInfobeanInfo=Introspector.getBeanInfo(person.getClass());
/*BeanInfo不能直接获取到对应的属性描述器,只能获取所有的属性描述器*/
PropertyDescriptorpropertyDescriptors[]=beanInfo.getPropertyDescriptors();
/*循环判断是不是我们需要使用的属性描述器*/
PropertyDescriptorneedDescriptor=null;
for(PropertyDescriptorpd:propertyDescriptors) {
/*判断是不是我们需要的属性描述器*/
if("name".equals(pd.getName())) {
needDescriptor=pd;
break;
}
}
/*获得person的setName()方法的Method对象*/
MethodmathodSetName=needDescriptor.getWriteMethod();
MethodmethodGetName=needDescriptor.getReadMethod();
/*打印mathodSetName的调用结果,相当于执行了person的setName()方法*/
mathodSetName.invoke(person,"王五");
System.out.println(methodGetName.invoke(person));
}
}
程序输出:
李明
王五
一般,内省和反射都会结合使用,而且很多的Java框架都通用到了内省,比如Struts等。