內省概念及詳解(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());
      


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM