如何强制MOXy在懒惰初始化的Collection属性上使用setter?

时间:2014-03-07 20:57:56

标签: eclipselink jaxb2 moxy

给出这样的bean:

public class MyBean {
    private List<Something> things;

    private List<Something> internalGetThings() {
        if (things == null) {
            things = new ArrayList<Something>();
        }
        return things;
    }

    public Iterable<Something> getThings() {
        return <an immutable copy of internalGetThings()>;
    }

    public void setThings(List<Something> someThings) {
        things.clear();
        for (Something aThing : someThings) {
            addThing(aThing);
        }
    }

    public void addThing(Something aThing) {
        things.add(aThing);
        // Do some special stuff to aThing
    }
}

使用外部映射文件时,我这样映射:

<xml-element java-attribute="things" name="thing" type="com.myco.Something" container-type="java.util.ArrayList" /> 

似乎每个人都通过调用getThings().add()将某事添加到MyBean中。这是一个问题,因为getThings()返回列表的不可变副本,这是一个懒惰的初始化。如何配置映射(我使用的是外部映射文件,而不是注释),以便MOXy使用setThings()addThing()代替?

2 个答案:

答案 0 :(得分:1)

为什么JAXB / MOXy首先检查收集方法?

JAXB(JSR-222)实现使您有机会将您的属性设置为List接口,并仍然利用您选择使用的基础List实现。为实现此目的,JAXB实现将调用get方法以查看List实现是否已初始化。它将使用List方法填充add

public List<String> getThings() {
    if(null == things) {
        things = new ArrayList<String>();
    }
    return things;
}
public List<String> getThings() {
    if(null == things) {
        things = new LinkedList<String>();
    }
    return things;
}

如果你没有预先初始化List属性,那么MOXy / JAXB将构建List的实例(默认为ArrayList)并使用设定方法。

private List<Something> things; // Don't Initialize

public List<String> getThings() {
    return things;
}

public void setThings(List<String> things) {
    this.things = things;
}

答案 1 :(得分:1)

鉴于@ Blaise的答案中的原因,似乎不可能有MOXy(或任何一般的JAXB实现?)通过集合上的setter方法填充一个延迟初始化的集合。但是,xml-accessor-type="FIELD"(或@XmlAccessorType,如果使用注释)和定义JAXB unmarshal event callback的组合将完成工作。在我的afterUnmarshal()实现中,我对addSomething()中完成的Something实例进行了特殊处理。

private void afterUnmarshal(Unmarshaller, Object parent) {
    for (Something aThing : getSomethings()) {
        // Do special stuff on aThing
    }
}

使用FIELD访问类型使JAXB / MOXy直接将集合注入到字段中,绕过getter。然后回叫清理正确。