Java内省机制
转自: 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(2, 5); /*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, 8); System.out.println(point.getX()); //8 }
第二个是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); //2 }
第三个是通过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)); //2 break; } }
对内省的实际应用工具是BeanUtils, 这是Web项目中,通过populate,实现将前台获取的数据直接封装到JavaBean中
类似的工具还有PropertyUtils, 两者的区别在于:BeanUtils获取的属性值的类型全部转为String类型,而PropertyUtils则是保留原有的数据类型.
posted on 2018-08-31 11:19 Yiran_shampin 阅读(181) 评论(0) 收藏 举报