在bean上设置深度属性,根据需要创建中间实例

时间:2013-10-22 13:16:45

标签: java javabeans apache-commons-beanutils

我正在使用BeanUtils.setProperty在bean上设置深层属性。

Home home = new Home() ;
String path = "home.family.father.age";
Integer value = 40;

BeanUtils.setProperty(home, path, value);
// Does the same as home.getHome().getFamily().getFather().setAge(value);
// But stops on null (instead of throwing an NPE).

如果其中一个中间属性是null,BeanUtils的行为就是什么都不做。例如,在我的情况下,home的{​​{1}}属性为family,没有任何反应。如果我做

null

然后family = new Family(); 将为null,我也必须初始化它。显然,我的真实用例更复杂,有许多动态属性(以及索引的属性)。

有没有办法告诉BeanUtils实例化中间成员?我知道通常这是不可能的(因为可能不知道属性的具体类型)。但在我的情况下,所有属性都有具体的类型,并且是正确的bean(使用公共的无参数构造函数)。所以有可能。

我想确保在推出自己的解决方案之前还没有现成的解决方案(使用BeanUtils或其他方法)。

1 个答案:

答案 0 :(得分:1)

我自己动手了。它只支持简单的属性,但我想添加对嵌套/映射属性的支持不会太难。

如果有人需要同样的事情,这是一个要点: https://gist.github.com/ThomasGirard/7115693

以下是最重要的部分:

/** Mostly copy-pasted from {@link PropertyUtilsBean.setProperty}. */
public void initProperty(Object bean, String path) throws SecurityException, NoSuchMethodException,
        IllegalAccessException, InvocationTargetException {

    // [...]

    // If the component is null, initialize it
    if (nestedBean == null) {

        // There has to be a method get* matching this path segment
        String methodName = "get" + StringUtils.capitalize(next);
        Method m = bean.getClass().getMethod(methodName);

        // The return type of this method is the object type we need to init.
        Class<?> propType = m.getReturnType();
        try {
            // Since it's a bean it must have a no-arg public constructor
            Object newInst = propType.newInstance();
            PropertyUtils.setProperty(bean, next, newInst);
            // Now we have something instead of null
            nestedBean = newInst;
        } catch (Exception e) {
            throw new NestedNullException("Could not init property value for '" + path + "' on bean class '"
                    + bean.getClass() + "'. Class: " + propType);
        }
    }

    // [...]

}