2016-01-11 58 views
4

這個問題似乎很尷尬,但我們在檢索javabean的PropertyDescriptors時遇到了一個奇怪的行爲。 下面是1.6,1.7和1.8的一個簡單的代碼執行結果,編譯1.6符合。JRE 1.8仍然遵循關於IndexedPropertyDescriptor的JavaBean規範嗎?

Java 1.6的執行:

[email protected] < - 不重要 [email protected] < - 是的,我有一個索引屬性

的Java 1.7執行:

java.beans.PropertyDescriptor [name = class; propertyType = class java.lang.Class; readMethod = public final native java.lang.Class java.lang.Object.getClass()] < - 不重要 java.beans.IndexedPropertyDescriptor [name = values; indexedPropertyType = class java.lang.String; indexedReadMethod =公共java.lang.String中JavaBean.getValues(INT)] < - 是的,我有一個索引屬性

的Java 1.8執行:

java.beans.PropertyDescriptor中的[名稱= A類; propertyType = class java.lang.Class; readMethod = public final native java.lang.Class java.lang.Object.getClass()] < - 不重要 java.beans.PropertyDescriptor [name = values; propertyType = interface java.util.List; readMethod = public java.util.List JavaBean.getValues()] < - Ouch!這不再是索引的屬性!

它爲什麼改變了?

javabean規範說明了如何使用索引訪問屬性。它不是強制性的使用數組作爲索引屬性的容器。我錯了嗎?

我閱讀規範和章節8.3.3談論索引屬性的設計模式,而不是嚴格的規則。

如何在不重構所有應用程序的情況下使以前的行爲再次迴歸? <舊的應用程序,大量的代碼修改,等等

感謝您的答案,

JavaBean類

import java.util.ArrayList; 
import java.util.List; 


public class JavaBean { 


    private List<String> values = new ArrayList<String>(); 


    public String getValues(int index) { 
    return this.values.get(index); 
    } 


    public List<String> getValues() { 
    return this.values; 
    } 
} 

主要類

import java.beans.IntrospectionException; 
import java.beans.Introspector; 
import java.beans.PropertyDescriptor; 

public class Test { 
    public static void main(String[] args) throws IntrospectionException { 
     PropertyDescriptor[] descs = 
     Introspector.getBeanInfo(JavaBean.class).getPropertyDescriptors(); 
     for (PropertyDescriptor pd : descs) { 
     System.out.println(pd); 
     } 
    } 
} 

回答

2

利用JavaBeans 1.01規範,第7.2節「索引屬性」:

組件也可能將索引屬性公開爲單個數組值。

8.3節描述了在沒有顯式BeanInfo的情況下,introspection可以識別的設計模式。 8.3.3節說只有數組屬性會觸發索引屬性的自動識別。

你在技術上是正確的;它不是強制性的使用數組。但是如果你不這樣做,規範說你必須提供你自己的BeanInfo來將該屬性公開爲索引屬性。

因此,您的問題標題的答案是:是的,Java 1.8符合JavaBean規範。

我不知道爲什麼列表屬性曾經被支持。也許未來的JavaBeans規範將支持它們,因爲它已被撤銷。

至於你的最後一個問題:我認爲你必須爲每個具有List屬性的類創建一個BeanInfo類。我希望你可以創建一個通用的超類,使其更容易,如下所示:

public abstract class ListRecognizingBeanInfo 
extends SimpleBeanInfo { 

    private final BeanDescriptor beanDesc; 
    private final PropertyDescriptor[] propDesc; 

    protected ListRecognizingBeanInfo(Class<?> beanClass) 
    throws IntrospectionException { 
     beanDesc = new BeanDescriptor(beanClass); 

     List<PropertyDescriptor> desc = new ArrayList<>(); 

     for (Method method : beanClass.getMethods()) { 
      int modifiers = method.getModifiers(); 
      Class<?> type = method.getReturnType(); 

      if (Modifier.isPublic(modifiers) && 
       !Modifier.isStatic(modifiers) && 
       !type.equals(Void.TYPE) && 
       method.getParameterCount() == 0) { 

       String name = method.getName(); 
       String remainder; 
       if (name.startsWith("get")) { 
        remainder = name.substring(3); 
       } else if (name.startsWith("is") && 
          type.equals(Boolean.TYPE)) { 
        remainder = name.substring(2); 
       } else { 
        continue; 
       } 

       if (remainder.isEmpty()) { 
        continue; 
       } 

       String propName = Introspector.decapitalize(remainder); 

       Method writeMethod = null; 
       Method possibleWriteMethod = 
        findMethod(beanClass, "set" + remainder, type); 
       if (possibleWriteMethod != null && 
        possibleWriteMethod.getReturnType().equals(Void.TYPE)) { 

        writeMethod = possibleWriteMethod; 
       } 

       Class<?> componentType = null; 
       if (type.isArray()) { 
        componentType = type.getComponentType(); 
       } else { 
        Type genType = method.getGenericReturnType(); 
        if (genType instanceof ParameterizedType) { 
         ParameterizedType p = (ParameterizedType) genType; 
         if (p.getRawType().equals(List.class)) { 
          Type[] argTypes = p.getActualTypeArguments(); 
          if (argTypes[0] instanceof Class) { 
           componentType = (Class<?>) argTypes[0]; 
          } 
         } 
        } 
       } 

       Method indexedReadMethod = null; 
       Method indexedWriteMethod = null; 

       if (componentType != null) { 
        Method possibleReadMethod = 
         findMethod(beanClass, name, Integer.TYPE); 
        Class<?> idxType = possibleReadMethod.getReturnType(); 
        if (idxType.equals(componentType)) { 
         indexedReadMethod = possibleReadMethod; 
        } 

        if (writeMethod != null) { 
         possibleWriteMethod = 
          findMethod(beanClass, writeMethod.getName(), 
           Integer.TYPE, componentType); 
         if (possibleWriteMethod != null && 
          possibleWriteMethod.getReturnType().equals(
           Void.TYPE)) { 

          indexedWriteMethod = possibleWriteMethod; 
         } 
        } 
       } 

       if (indexedReadMethod != null) { 
        desc.add(new IndexedPropertyDescriptor(propName, 
         method, writeMethod, 
         indexedReadMethod, indexedWriteMethod)); 
       } else { 
        desc.add(new PropertyDescriptor(propName, 
         method, writeMethod)); 
       } 
      } 
     } 

     propDesc = desc.toArray(new PropertyDescriptor[0]); 
    } 

    private static Method findMethod(Class<?> cls, 
            String name, 
            Class<?>... paramTypes) { 
     try { 
      Method method = cls.getMethod(name, paramTypes); 
      int modifiers = method.getModifiers(); 
      if (Modifier.isPublic(modifiers) && 
       !Modifier.isStatic(modifiers)) { 

       return method; 
      } 
     } catch (NoSuchMethodException e) { 
     } 

     return null; 
    } 

    @Override 
    public BeanDescriptor getBeanDescriptor() { 
     return beanDesc; 
    } 

    @Override 
    public PropertyDescriptor[] getPropertyDescriptors() { 
     return propDesc; 
    } 
} 
+0

那麼......我預計這種答案。我仍然不明白爲什麼這種行爲會以這種方式發生變化,而不是更嚴格的實施。無論如何,這是個很好的答案謝謝。因爲我們使用的是commons-beanutils,所以我最好通過使用BeanIntrospector來擴展這個API的功能,這個BeanIntrospector可以在自我定義的同時檢測一個IndexedProperty,同時反省一個bean。 –