内省概念及详解(MethodDescriptor、PropertyDescriptor)

  1. 内省(Introspector)概念

    ​ 内省Introspector 是Java提供的操作 JavaBean 的 API,用来访问某个属性的 getter/setter 方法。对于一个标准的 JavaBean 来说,它包括属性、get 方法和 set 方法,这是一个约定俗成的规范。为此 sun 提供了 Introspector 工具包,来使开发者更好或者更灵活的操作 JavaBean。

    例如:User类中有个name属性,那我们可以通过getName/setName来获取/设置name的值,内省就是通过Java提供的API访问属性的getName()/setName()方法。

  2. 内省与反射的区别

    ​ 在计算机科学中,内省是指计算机程序在运行时(Run time)检查对象(Object)类型的一种能力,通常也可以称作运行时类型检查。 不应该将内省和反射混淆。相对于内省,反射更进一步,是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。

  3. 内省常用类说明

    • 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),设置用于读取/写入属性值的方法
  4. 代码演示

    • 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());
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值