2011-02-02 23 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)); 
相关问题