2011-02-02 26 views
5
私は PropertyUtils.setProperty(オブジェクト、名前、値)のApache Commonsの豆の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 class'クラスAの 'bc'のNullプロパティ値 '

PropertyUtilsにネストされたプロパティがnull値を持つ場合、それをインスタンス化しようとする前に(デフォルトのコンストラクタ)深く進むように指示できますか?

他の方法はありますか?

は、いくつかの研究を行った後に短い答えます

答えて

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

あなたがNULL BにCを設定しようとすると、これが問題になります最善の方法は、リフレクションを使用してオブジェクトを横断して、それを作成することです道に沿って。 –

-1

ありがとう「ことが可能ですが...」という質問がませではありません。

2

少し訂正:

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

あなたは正しいですよ! –

0

を、私はこれを達成するために/ OのApacheライブラリwの反射のみを使用していました。トラバースされるすべてのオブジェクトはすべて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で利用できる非常に類似した機能」がある。良いが、まだそれがあまりにもリストと配列を扱う。上記のdocリンクは春です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)); 
関連する問題