内省详解(Introspector/BeanInfo/MethodDescriptor/PropertyDescriptor)
-
内省(Introspector)概念
内省Introspector 是Java提供的操作 JavaBean 的 API,用来访问某个属性的 getter/setter 方法。对于一个标准的 JavaBean 来说,它包括属性、get 方法和 set 方法,这是一个约定俗成的规范。为此 sun 提供了 Introspector 工具包,来使开发者更好或者更灵活的操作 JavaBean。
例如:User类中有个name属性,那我们可以通过getName/setName来获取/设置name的值,内省就是通过Java提供的API访问属性的getName()/setName()方法。
-
内省与反射的区别
在计算机科学中,内省是指计算机程序在运行时(Run time)检查对象(Object)类型的一种能力,通常也可以称作运行时类型检查。 不应该将内省和反射混淆。相对于内省,反射更进一步,是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。
-
内省常用类说明
-
Introspector
类提供了的 getBeanInfo()方法获取BeanInfo对象,可以拿到一个 JavaBean 的所有信息 -
BeanInfo
通过getPropertyDescriptors() 方法和 getMethodDescriptors()方法可以获取到PropertyDescriptors、MethodDescriptors对象 -
MethodDescriptor
类可以获得方法的元信息,比如方法名,参数个数,参数字段类型等- getMethod()获取方法的Method对象
- getParameters() 获取方法的所有参数Parameter列表
- getParameterTypes()获取方法的参数ParameterType列表
-
PropertyDescriptor
类的主要方法- getPropertyType(),获得属性的Class对象
- getReadMethod()/getWriteMethod(),获得用于读取/写入属性值的方法
- setReadMethod(Method readMethod)/setWriteMethod(Method writeMethod),设置用于读取/写入属性值的方法
-
-
代码演示
-
MethodDescriptor
详解// 使用Introspector获取BeanInfo对象 BeanInfo beanInfo = Introspector.getBeanInfo(User.class); // 使用BeanInfo对象获取到MethodDescriptor列表 MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors(); for (MethodDescriptor methodDescriptor : methodDescriptors) { // 获取方法Method对象 Method method = methodDescriptor.getMethod(); // 获取方法名称 String methodName = method.getName(); // 参数类型列表 List<String> parameterTypeNames = new ArrayList<>(); Class<?>[] parameterTypes = method.getParameterTypes(); if (parameterTypes!=null && parameterTypes.length>0){ Arrays.stream(parameterTypes).forEach(x-> { String name = x.getName(); parameterTypeNames.add(name); }); } // 获取方法参数Parameter数组 Parameter[] parameters = method.getParameters(); // 参数名称列表 List<String> parameterNames = new ArrayList<>(); if (parameters!=null && parameters.length>0){ parameterNames = Arrays.stream(parameters).map(Parameter::getName).collect(Collectors.toList()); } System.out.println("方法名称:"+methodName +" 参数类型列表:"+parameterTypeNames+" 参数名称列表:"+parameterNames);
-
PropertyDescriptors
详解// 使用Introspector获取BeanInfo对象 BeanInfo beanInfo = Introspector.getBeanInfo(User.class); // 使用BeanInfo对象获取到PropertyDescriptor列表 PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor propertyDescriptor :propertyDescriptors) { // 获取属性名称 String name = propertyDescriptor.getName(); if ("class".equals(name)){ continue; } // 获取setter方法 Method writeMethod = propertyDescriptor.getWriteMethod(); // 获取getter方法 Method readMethod = propertyDescriptor.getReadMethod(); System.out.println("属性名称:"+name+ " 赋值方法:"+writeMethod.getName()+ " 获取方法:"+readMethod.getName()); } // 利用反射创建对象 User user = User.class.newInstance(); // 创建PropertyDescriptor对象 PropertyDescriptor propertyDescriptor = new PropertyDescriptor("name",User.class); // 获取写入方法并执行 Method writeMethod = propertyDescriptor.getWriteMethod(); writeMethod.invoke(user,"Rangers"); // 获取读取方法并执行 Method readMethod = propertyDescriptor.getReadMethod(); Object readPropertyValue = readMethod.invoke(user); System.out.println("ReadMethod获取到到属性值:"+readPropertyValue); System.out.println("getter获取到到属性值:"+user.getName()); // 设置写入方法并执行 Method writeMd = User.class.getDeclaredMethod("setOoo",String.class); propertyDescriptor.setWriteMethod(writeMd); Method writeMethodAgain = propertyDescriptor.getWriteMethod(); writeMethodAgain.invoke(user, "ooo"); System.out.println("设置写入方法重新赋值:"+user.getName());
-