给出这样的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()
代替?
答案 0 :(得分:1)
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。然后回叫清理正确。