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 classPoint {privateInteger x;privateInteger y;publicPoint(Integer x, Integer y) {//super();
this.x =x;this.y =y;
}publicInteger getX() {returnx;
}public voidsetX(Integer x) {this.x =x;
}publicInteger getY() {returny;
}public voidsetY(Integer y) {this.y =y;
}
}
创建一个测试类
public static voidmain(String[] args) throws IllegalAccessException, IntrospectionException, InvocationTargetException {
Point point= new Point(2, 5);/*getProperty(point,"x");*/getPropertyChange(point,"getX");
setProperty(point,"x");
}
在测试类中创建测试方法
第一个是setProperty
//创建一个setProperty方法
private static voidsetProperty(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, 8);
System.out.println(point.getX()); //8
}
第二个是getProperty
//创建一个getProperty方法
private static voidgetProperty(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); //2
}
第三个是通过Introspector内省类
//创建一个getProperty修改方法
private static voidgetPropertyChange(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)); //2
break;
}
}
对内省的实际应用工具是BeanUtils, 这是Web项目中,通过populate,实现将前台获取的数据直接封装到JavaBean中
类似的工具还有PropertyUtils, 两者的区别在于:BeanUtils获取的属性值的类型全部转为String类型,而PropertyUtils则是保留原有的数据类型.