Java内省机制

时间:2022-06-01 18:53:26

转自: https://blog.csdn.net/hahalzb/article/details/5972421

1.java内省机制其实通俗的理解为,对自身的进行一个扫描,这个扫描的对象就是我们普通的Bean类, 这个Bean类要求至少要有一个getXxx或者setXxx方法,内省的类是Instrospector, 通过传入Bean类的字节码文件,就可以获取到BeanInfo对象,这个对象中保存了这个Bean类的所有字节码信息,竟然保存在里面,那么我们就肯定可以通过某些方法来进行数据的获取,这个就是描述器(descriptor).

描述器有PropertyDescriptor, MethodDescriptor. 分别为属性描述器和方法描述器. 他们都有一个getName的方法来获取对应的名称(例:属性是name,  那么PropertyDescriptor.getName = "name",   对应的方法是getName,那么MethodDescriptor.getName = "getName,  这个getName方法非常常用,因为通过这个方法来确认描述器的). 每一个属性或者每一个方法都只有一个描述器, 所有只要找到对应的描述器,就可以通过描述器进行数据的存储等操作.

下面进行简单的代码演示

首先创建一个Bean类

package cn.shampin.introspector.domain;

public class Point {
private Integer x;
private Integer y; public Point(Integer x, Integer y) {
// super();
this.x = x;
this.y = y;
} public Integer getX() {
return x;
} public void setX(Integer x) {
this.x = x;
} public Integer getY() {
return y;
} public void setY(Integer y) {
this.y = y;
}
}

创建一个测试类

public static void main(String[] args) throws IllegalAccessException, IntrospectionException, InvocationTargetException {
Point point = new Point(, ); /*getProperty(point,"x");*/
getPropertyChange(point,"getX");
setProperty(point,"x"); }

在测试类中创建测试方法

第一个是setProperty

//创建一个setProperty方法
private static void setProperty(Point point, String proName) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
//通过属性描述器PropertyDescriptor,来访问属性的getter/setter方法
//参数为属性名称和javaBean字节码,获取该属性的描述器
PropertyDescriptor descriptor = new PropertyDescriptor(proName, Point.class);
System.out.println(descriptor);
//通过描述器的getWriteMethod就是获取 setXxxx方法反射实例,可以进行方法的设置
Method writeMethod = descriptor.getWriteMethod();
System.out.println(writeMethod);
//反射实例调用invoke方法,实现方法的调用
writeMethod.invoke(point, );
System.out.println(point.getX()); //
}

第二个是getProperty

//创建一个getProperty方法
private static void getProperty(Point point, String proName) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
PropertyDescriptor descriptor = new PropertyDescriptor(proName,Point.class);
Method readMethod = descriptor.getReadMethod();
Object invoke = readMethod.invoke(point);
System.out.println(invoke); //
}

第三个是通过Introspector内省类

//创建一个getProperty修改方法
private static void getPropertyChange(Point point, String proName) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
//通过类或者类的对象来获取当前类BeanInfo对象是同一个
//BeanInfo beanInfo = Introspector.getBeanInfo(Point.class);
//Introspetor就是内省
BeanInfo beanInfo = Introspector.getBeanInfo(point.getClass());
//获取当前BeanInfo对象的所有属性描述器,一个属性只有一个属性描述器,里面存储着当前属性的所有信息
//包括属性名称,属性数据类型,属性get/set方法
//Introspector 是一个专门处理bean的工具类.用来获取Bean体系里的 propertiesDescriptor,methodDescriptor.
//利用反射获取Method信息,是反射的上层.
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor prop : propertyDescriptors) {
/*System.out.println("getName:" + prop.getName()); //JavaBean属性名称
System.out.println("propertyType" + prop.getPropertyType()); //属性数据类型
System.out.println("propertyEC" + prop.getPropertyEditorClass()); //属性编辑器*/
//通过比对属性的名称,来寻找我们传入的属性proName的属性描述器
//通过属性描述器来对该属性进行相关的操作
Method readMethod = prop.getReadMethod();
if(readMethod.getName().equals(proName)){
Method methodGetx = prop.getReadMethod();
System.out.println(methodGetx.invoke(point)); //
break;
}
}

对内省的实际应用工具是BeanUtils, 这是Web项目中,通过populate,实现将前台获取的数据直接封装到JavaBean中

类似的工具还有PropertyUtils, 两者的区别在于:BeanUtils获取的属性值的类型全部转为String类型,而PropertyUtils则是保留原有的数据类型.