2011-02-02 57 views
5

我使用PropertyUtils.setProperty(對象名稱,值)阿帕奇百科全書豆utils的的方法:是否有可能使用Commons Bean Utils自動實例化嵌套Property?

給這些類:

public class A { 
    B b; 
} 

public class B { 
    C c; 
} 

public class C { 
} 

這:

A a = new A(); 
C c = new C(); 
PropertyUtils.setProperty(a, "b.c", c); //exception 

如果我嘗試獲得: org.apache.commons.beanutils.NestedNullException:bean類上的'bc'的Aull屬性值爲'A類 '

是否有可能告訴PropertyUtils,如果嵌套屬性有一個空值嘗試實例化它(默認構造函數),然後再嘗試更深入?

還有其他方法嗎?

謝謝

回答

8

我解決它通過這樣做:

private void instantiateNestedProperties(Object obj, String fieldName) { 
    try { 
     String[] fieldNames = fieldName.split("\\."); 
     if (fieldNames.length > 1) { 
      StringBuffer nestedProperty = new StringBuffer(); 
      for (int i = 0; i < fieldNames.length - 1; i++) { 
       String fn = fieldNames[i]; 
       if (i != 0) { 
        nestedProperty.append("."); 
       } 
       nestedProperty.append(fn); 

       Object value = PropertyUtils.getProperty(obj, nestedProperty.toString()); 

       if (value == null) { 
        PropertyDescriptor propertyDescriptor = PropertyUtils.getPropertyDescriptor(obj, nestedProperty.toString()); 
        Class<?> propertyType = propertyDescriptor.getPropertyType(); 
        Object newInstance = propertyType.newInstance(); 
        PropertyUtils.setProperty(obj, nestedProperty.toString(), newInstance); 
       } 
      } 
     } 
    } catch (IllegalAccessException e) { 
     throw new RuntimeException(e); 
    } catch (InvocationTargetException e) { 
     throw new RuntimeException(e); 
    } catch (NoSuchMethodException e) { 
     throw new RuntimeException(e); 
    } catch (InstantiationException e) { 
     throw new RuntimeException(e); 
    } 
} 
+0

當您嘗試設置C到一個NULL B.最好的辦法是使用反射來遍歷對象和創建它這將有問題一路走來 – 2015-07-27 04:49:40

-1

做一些研究之後,簡短的回答「是否有可能......」問題是沒有

2

小修正:

String fn = fieldNames[i]; 
if (i != 0) { 
     nestedProperty.append("."); 
} 
nestedProperty.append(fn); 
Object value = PropertyUtils.getProperty(obj, nestedProperty.toString()); 
+0

你是對的謝謝你! – 2011-03-14 21:14:33

0

我只用反射W/O型阿帕奇庫來實現這一目標。假定所有要遍歷的對象都是POJO,並且默認構造是可公開訪問的。這樣,就不需要爲每個循環構建參考路徑。

public Object getOrCreateEmbeddedObject(Object inputObj,String[] fieldNames) throws Exception { 

    Object cursor = inputObj; 

    //Loop until second last index 
    for (int i = 0; i < fieldNames.length - 1; i++){ 
     Field ff = getClassFieldFrom(cursor,fieldNames[i]); 
     Object child = ff.get(cursor); 
     if(null == child) { 
      Class<?> cls=ff.getType(); 
      child = cls.newInstance(); 
      ff.set(cursor, child); 
     } 
     cursor = child; 
    } 

    return cursor; 
} 

private Field getClassFieldFrom(Object object, String fieldStr) 
      throws NoSuchFieldException { 
     java.lang.reflect.Field ff = object.getClass().getDeclaredField(fieldStr); 
     ff.setAccessible(true); 
     return ff; 
} 

如果您對我的解決方案有任何建議,請告訴我。

0

我去的只是默認實例每個對象的非常基本的方法:

public class A { 
    B b = new B(); 
} 

public class B { 
    C c = new C(); 
} 

public class C { 
} 

不理想,但它的工作對我的情況,並沒有涉及複雜的修復。

3

我知道這個問題是關於Apache公地PropertyUtils.setProperty但它有非常類似的功能在 Spring Expression Language "SpEL「,這不正是你想要的東西。更妙的是它與列表和數組太對不起!上面的文檔鏈接是春天4.x的,但下面的代碼在春天3.2.9對我的作品。

StockOrder stockOrder = new StockOrder(); // Your root class here 

    SpelParserConfiguration config = new SpelParserConfiguration(true,true); // auto create objects if null 
    ExpressionParser parser = new SpelExpressionParser(config); 
    StandardEvaluationContext modelContext = new StandardEvaluationContext(stockOrder); 

    parser.parseExpression("techId").setValue(modelContext, "XXXYYY1"); 
    parser.parseExpression("orderLines[0].partNumber").setValue(modelContext, "65498"); 
    parser.parseExpression("orderLines[0].inventories[0].serialNumber").setValue(modelContext, "54686513216"); 

    System.out.println(ReflectionToStringBuilder.toString(stockOrder)); 
相關問題